!standard 9.6.1(4/2) 17-04-06 AC95-00288/00 !standard 9.6.1(6/2) !class confirmation 17-04-06 !status received no action 17-04-06 !status received 17-02-18 !subject Providing an indication of when daylight savings begins/ends !summary !appendix From: Tucker Taft Sent: Saturday, February 18, 2017 3:00 PM We have a customer who is worrying about what happens when they have a user requesting some job to be started, at say, 2:30AM, and it turns out to be the night when daylight savings begins or ends. It seems like it might be worth augmenting the Time_Zones.UTC_Time_Offset interface with a way to know whether it is the morning when daylight savings time begins or ends. Here are a couple of interfaces that Microsoft provides related to this: TimeZoneInfo.IsAmbiguousTime: https://msdn.microsoft.com/en-us/library/bb396403(v=vs.110).aspx TimeZoneInfo.GetAmbiguousTimeOffsets: https://msdn.microsoft.com/en-us/library/bb382127(v=vs.110).aspx *************************************************************** From: Randy Brukardt Sent: Saturday, February 18, 2017 6:35 PM You can detect that with the existing interfaces (assuming, of course, that they're implemented properly). The trick is to check if the Time_Offset is different for two nearby times that should be on different sides of the change. Something like the following should work: function Time_Change_Tonight return Boolean is -- Returns True if a time zone change will happen -- tonight (after midnight!) TZ_at_1am : Time_Offset; TZ_at_4am : Time_Offset; Now : Time := Ada.Calendar.Clock; Next_1am : Time; begin declare Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration; begin Split (Now, Year, Month, Day, Seconds); if Seconds < 7200.0 then Next_1am := Time_of (Year, Month, Day, 3600.0); -- 1am. else Next_1am := Time_of (Year, Month, Day, 3600.0) + 86400.0; -- 1am tomorrow. end if; end; TZ_at_1am := UTC_Time_Offset (Next_1am); TZ_at_4am := UTC_Time_Offset (Next_1am + (3600.0*3)); return TZ_at_1am /= TZ_at_4am; end Time_Change_Tonight; You can also use a pattern like this to determine the direction of change. (Such a pattern might not be accurate for times in the distant past or far in the future, but it should be fine for times that are near the current one.) This pattern will definitely work with the Janus/Ada implementation (can't speak for other compilers, of course). Thus, I don't find much need to add interfaces to the Standard (requiring everyone to implement them). They might be a bit more convinient, but the need doesn't seem that common. *************************************************************** From: Tucker Taft Sent: Sunday, February 19, 2017 9:48 AM > You can also use a pattern like this to determine the direction of change. > (Such a pattern might not be accurate for times in the distant past or > far in the future, but it should be fine for times that are near the > current > one.) Yes, I recommended something pretty similar. But it would seem easy enough to have something that would identify the day and time of start/end of daylight savings. > This pattern will definitely work with the Janus/Ada implementation > (can't speak for other compilers, of course). > > Thus, I don't find much need to add interfaces to the Standard > (requiring everyone to implement them). They might be a bit more > convenient, but the need doesn't seem that common. I suppose, but it seems silly to hide the information that clearly must be present in the implementation. *************************************************************** From: Erhard Ploedereder Sent: Sunday, February 19, 2017 2:42 PM > I suppose, but it seems silly to hide the information that clearly > must be present in the implementation. but it isn't necessarily. I would expect that Ada.Calendar maps to similar OS-calendar services which may or may not expose this information. It is a pain in the ... to retain information about when the switch-overs occur, since they are different in different countries. By the way, replace Next_1am := Time_of (Year, Month, Day, 3600.0 + 86400.0); by Next_1am := Time_of (Year, Month, Day, 3600.0) + 86400.0; in Randy's code. [Editor's note: The correction was made in the example above, in case someone wanted to run it and didn't read the entire thread.] *************************************************************** From: Tucker Taft Sent: Monday, February 20, 2017 8:05 AM >> I suppose, but it seems silly to hide the information that clearly >> must be present in the implementation. > > but it isn't necessarily. I would expect that Ada.Calendar maps to > similar OS-calendar services which may or may not expose this > information. It is a pain in the ... to retain information about when > the switch-overs occur, since they are different in different > countries. ... Good point. I was naively thinking it was in the Ada RTS, but of course it is in the underlying O/S, and as you point out, the O/S might not expose the needed information in any portable interface. *************************************************************** From: Randy Brukardt Sent: Monday, February 20, 2017 4:49 PM Just to clarify, that was what I was thinking (even though I didn't explicitly state it). The information about future time changes is available in the Windows API, but I don't know if that is true on other targets. And since we didn't need that information to answer the specific question posed, it seemed better to avoid making additional requirements on the target. (It would be fairly complex to answer the question even if that information was available given that there are two time changes per year -- it wouldn't be appreciably shorter than the solution I gave. One can imagine other questions that would be easier to answer, but those probably ought to be left in the "question not asked" territory.) ***************************************************************