Leap Seconds for the AppDev: What you should know

Author: Travis Luke

Last week my esteemed colleague Dan Cuomo introduced Leap Seconds support for Windows 10 including what you need to know if you’re an IT Pro.

If you’re an application developer, the things you need to know are a little bit different. I’m sure all of you were wondering how your application take advantage of the ‘60’ second?  How can you accurately measure time and time durations during leap seconds?  And how can frameworks and applications that calculate time stay in sync with the Operating System?  So, in this article, I’ll attempt to explain all that and describe some of the details and considerations needed to support leap seconds in your application.

Before we get into the details of what developers should consider, let’s have a brief history of measuring time and the birth of the Leap Second.  As we all know (🙂), the Gregorian calendar has a set standard of measuring intervals for time.

  • 1000 milliseconds per second.
  • 60 seconds per minute
  • 60 seconds per hour
  • 60 minutes in every hour
  • 24 hours in every day
  • Months have a variable (but repeatable pattern) for the number of days in a month, ranging from 28 to 31.  And years have 365 days.

The big exception to that is leap years.  (Almost) every 4 years a day is added to February to create a 366-day year.  What is convenient about all of this is it is very predictable.  We can say with certainty how time will be counted in the coming years, decades, and centuries, down to the millisecond.

However, Leap Seconds are not a predictable event.  An International committee called IERS periodically decides to insert a leap second based on observations of the rotation of the earth.  Every six months there is an announcement about whether a leap second will or will not be added or subtracted. This extra second occurs on either June 30th or December 31st.  The timing of this event occurs at the same time all over the globe, at 23:59:59 UTC.

If a second is added the official clock will switch move in 1000 ms increments from 23:59:59 UTC to 23:59:60 UTC to 00:00:00 UTC.  If a second is subtracted (which has never happened so far) time would move in 1000 ms increments from 23:59:58 UTC to 00:00:00.

When IERS publishes a leap second event this data will arrive to all Windows PCs through a few mechanisms.  It may get this data when it is syncing its time through a NTP server.  By default, windows syncs with an NTP time source, such as time.windows.com every day.  It may also receive this data through Windows Update. When this data arrives, it is stored in the Operating System.  This allows Windows to operate on the knowledge of those events.

Windows uses a structure called FILETIME to record a timestamp. (If you are curious like me, you may wonder why it is called filetime. This is because it was originally used only in the Windows File System to represent the timestamp of a file. This structure is now used throughout the operating system for all timestamp related scenarios). The FILETIME structure represent the number of 100 nanosecond intervals since Jan 1, 1601.  There are several APIs that are available to convert this value into a more readable form.  For example FileTimeToSystemTime will convert the FILETIME into a SYSTEMTIME structure representing the UTC time of that value.  The SYSTEMTIME structure provides a breaks down the year, month, day, hour, minute, and second values.

Starting in Server 2019 and the Windows 10 October update time APIs will now take into account all leap seconds the Operating System is aware of when it translates FILETIME to SystemTime. No change is made to FILETIME. It still represents the number of 100 ns intervals since the start of the epoch. What has changed is the interpretation of that number when it is converted to SYSTEMTIME and back. Here is a list of affected APIs:

  • GetSystemTime
  • GetLocalTime
  • FileTimeToSystemTime
  • FileTimeToLocalTime
  • SystemTimeToFileTime
  • SetSystemTime
  • SetLocalTime

Previous to this release, SYSTEMTIME had valid values for wSecond between 0 and 59.  SYSTEMTIME has now been updated to allow a value of 60, provided the year, month, and day represents day in which a leap second is valid.

 

Here are number of Frequently Asked Questions about developing Leap Second Aware Applications:

How can applications take advantage of the ‘60’ second? 

In order receive the 60 second in the SYSTEMTIME structure a process must explicitly opt-in.  You can have your process do this by calling SetProcessInformation with the ProcessLeapSecondInfo option.

DWORD ErrorCode;
BOOL Success;
PROCESS_LEAP_SECOND_INFO LeapSecondInfo;
ZeroMemory(&LeapSecondInfo, sizeof(LeapSecondInfo));
Success = SetProcessInformation(GetCurrentProcess(),
                                ProcessLeapSecondInfo, 
                                &LeapSecondInfo,
                                sizeof(LeapSecondInfo));
if (!Success) {
                  ErrorCode = GetLastError();
                  fprintf(stderr, "Set Leap Second priority failed: %d\n", ErrorCode);
                  goto cleanup;
}

By calling this you are telling the operating system that your application will accept a SYSTEMTIME structure with the values between 0 and 60.  Applications are expected to handle the 60 value in a way that makes sense.  For example, if your application is showing transactions in a list with a time stamp, it will display the timestamp with the 23:59:60 value.   Or if your application is an analog clock it may play a special animation to indicate a leap second is occurring.

Application developers are encouraged to test their application with the process opted in.  We have provided a simple method to the opted in behavior without recompiling your code. Please check our previous blog entry on Leap Seconds for the IT Pro which has a section named “Testing Applications” that provides a method to opt-in through the registry.

You can also see examples of how to insert leap seconds yourself for testing purposes using w32tm.exe.

 

How can application developers ensure their application is Leap Second compatible? 

There is a valid concern that if the SYSTEMTIME structure displayed a Seconds value of 60 that it would break applications that are not leap second aware.  Imagine your application was an analog clock.  It may be assuming that valid values of the seconds is between 0 and 59.  If it is 60 it may crash as it attempts to calculate the angle to draw the second hand.

To address this, by default all processes are in a “compatibly mode” unless they explicitly opt in to receive the ‘60’ second.  In the compatibility mode the second value will be guaranteed to be between 0 and 59.  In the second before a leap second is added, or at the ‘59’ second, the clock will slow down to half speed for two seconds.  This will have the visual effect of the 59 second being twice as long.  During this time the milliseconds values will also be slowed down by ½.  When this 2000 milliseconds is complete the clock will resume incrementing at normal speed.  This has the effect of giving applications the leap second and allowing for all timestamps that occur during the “slowdown” period to be sorted in the correct order they occurred. To reiterate, the above is the default behavior while in compatibility mode.

 

How can you accurately measure time and time durations during leap seconds?

One question that frequently comes up is how do you measure a time duration?  Say you want to add 1 day to an existing time stamp.  Does that mean adding 24 hours, or 1,440 minutes, or 86,400 to a given time stamp?  Or does that mean adding 1 day, regardless of how many seconds that day has (including possible leap seconds).  If what you want is to add 86,400 seconds you can follow the guidance here.  In this case you are taking the FILETIME structure, and moving it forward a specific number of milliseconds to achieve one normal day worth of time.

On the other hand, if you want to increment one day regardless of the seconds in that day then there is another approach you must use. In this case you convert your FILETIME to a SYSTEMTIME structure using FileTimeToSystemTime.  Then add the number of days to the structure.  Then covert it back to a FILETIME using the SystemTimeToFileTime API.  This will allow the operating system to apply the arithmetic to covert the SYSTEMTIME to a FILETIME, while factoring in any known leap seconds.

Care must be taken when FILETIME values are passed between computers.  If a FILETIME value is generated on an older windows PC or from a non-Windows PC then it may not be taking into account Leap Seconds.  If that FILETIME was then converted to a SYSTEMTIME structure on a PC that does take into account leap seconds, then the intended time may be off.  To correct for this a registry key has been provided which disables all leap second logic.  If you set this registry key then all behavior involving SYSTEMTIME and leap seconds is reverted.  If you are passing FILETIME values in a heterogeneous environment, you may consider setting this key. You can find more details about this in here under the subject “Revert to Prior OS Behavior”.

 

How can frameworks and applications that calculate time stay in sync with the Operating System? 

Some frameworks and applications may attempt to calculate time using their own arithmetic.  For example, the .NET Framework has logic in the System.DateTime structure to represent time.  If the implementation of the calculation of time is not handled by the operating system, then the framework may arrive at a different time then the Operating System.  For example, imagine if you called DateTime.Now one month after a leap second occurred.  The framework would call GetSystemTimeAsFileTime to get the FILETIME of the current moment.  It would then store this value inside the structure.  When a user wanted to know the date they may call the .ToString() function.  If this framework was attempting to perform its own arithmetic to turn that time into year, month, day, hour, minute, second value, and didn’t take into account the leap second, then the time it returned would be one second faster than the time the operating system reported. For each leap second that was added to the system the framework would continue to drift forward in time.  To correct this the .NET Framework updated the implementation to call the FileTimeToSystemTime API.  This allows the operating system rather than the framework to account all leap seconds and perform the proper arithmetic.

Applications that rely on 3rd party frameworks should ensure their framework’s implementation on Windows is also calling into the correct APIs to calculate the correct time, or else the application will have the wrong time reported.

 

Does the .NET framework support Leap Seconds?

At the time of this writing the System.DateTime structure does not account for leap seconds. It effectively runs in compatibility mode as described in the above section. In other words, during the moment of a leap second the ‘59’ second will be twice as long. Stay tuned for updates as greater leap second support is added to the .NET Framework.

 

How can I prevent Leap Seconds from occurring?

We have had a lot of discussion about this. We are thinking of organizing a day of everybody who is against leap seconds to run west. This will hopefully have the effect of changing the rotation of the earth and eliminate the need of the leap second.

 

We recommend all developers to make their applications leap second aware. We encourage you to try out the tools we provided to test your applications and choose the approaches that work for your scenarios. We are eager to hear back from the development community their experiences with Leap Seconds.

Thanks for reading,

Travis Luke