[LEAPSECS] leapseconds, converting between GPS time (week, second) and UTC

Paul Hirose cfuhb-acdgw at earthlink.net
Wed Jan 16 03:00:55 EST 2019


On 2019-01-15 10:50, Tom Van Baak wrote:
>> For instance, in Python, if I do a datetime(2016,12,31,0,0,0) +
>> timedelta(hours=30) does it come out as 1/1/2017 6:00:00 or 5:59:59  (it
>> comes out 0600)

Here's a C# code fragment which performs a similar computation. To make 
the demonstration more interesting I arrange for the augmented UTC to 
fall in the middle of a leap second.

The program calls my SofaJpl fundamental astronomy DLL for the Windows 
.NET Framework. "Sofa" refers to the IAU SOFA (Standards of Fundamental 
Astronomy) library, and "Jpl" refers to the Jet Propulsion Laboratory 
planetary ephemerides. But there's no astronomy in this little example.


// Open the leap second table. The '@' prefix on the
// string causes the C# compiler to not interpret a backslash as an
// escape character.
SofaJpl.Utc.LoadTableFromFile(@"C:\Users\Stan\Documents\astro\IERS\leapSecTable.txt");

// Construct a Utc object at the initial epoch.
SofaJpl.Utc utc1 = new SofaJpl.Utc(2016, 12, 31, 0, 0, 0);

// Construct a JulianDate object at the same epoch (TT scale).
SofaJpl.JulianDate tt = utc1.TerrestrialTime;

// Construct a Duration object with the amount of time to add.
SofaJpl.Duration timeIncrement = SofaJpl.Duration.FromSeconds(86400.5);

// Add the time to TT.
tt += timeIncrement;

// Convert the incremented TT to a new Utc object.
SofaJpl.Utc utc2 = new SofaJpl.Utc(tt);

// The desired time display precision (the unit is 1 / hours).
double timePrecision = 36000.0;     // .1 s precision

// Display the initial and final UTC epochs.
Console.WriteLine(utc1.ToTimeFields(timePrecision));
Console.WriteLine(utc2.ToTimeFields(timePrecision));


Output:
2016-12-31T00:00:00.0
2016-12-31T23:59:60.5

The leap second table follows the USNO format with some extensions. 1) 
For easy updates by hand, the Julian date field is ignored and may be 
blank. 2) The final line must have the same TAI-UTC as the previous 
line, but a later date. This line defines the final epoch of the table. 
An exception occurs if you exceed it.

http://maia.usno.navy.mil/ser7/tai-utc.dat

The "rubber second" era is supported. That accounted for about 90% of 
the workload to create the UTC implementation!

JulianDate and Duration objects both represent whole days and fractional 
days in separate double precision variables. Operators are defined if 
they make sense. For instance, if you subtract one JulianDate from 
another the result is a Duration. You can add two Durations but addition 
of two JulianDates is undefined. For convenience, the Duration class 
includes the fixed offsets TTMinusGps and TTMinusTai. Time conversions 
with variable offsets such as TTToTdb() are in the JulianDate class.

By design, the Utc class has limited facilities. You can create a Utc 
object from date and time components or a JulianDate in the TT scale. 
The inverse operations are available too. But as shown in the example, 
any time math requires explicit conversion to a JulianDate object in the 
TT scale, then conversion back to a Utc object if the user needs to see 
the result in UTC. These conversions are lossless since a Utc object 
internally stores its value as a JulianDate in TT. (The DLL is intended 
for astronomy, where TT is more useful than TAI.)

By not defining addition or subtraction on Utc objects I avoid ambiguity 
about the exact meaning of these operations in a stepped time scale.

A TimeFields represents epoch as year, month, etc. (It's not called 
"DateTime" because the Windows .NET Framework already has such a class.) 
The main purpose of the class is to format JulianDate and Utc objects 
for output, rounded to the specified precision. For example, if a 
JulianDate is a few seconds from the end of the year, and precision is 
60 (= one minute), the conversion to a TimeFields rounds up to January 1 
00:00 in the next year.

It's possible to construct named TimeFields objects and extract the 
components individually for output. But for simplicity my example 
creates unnamed objects. By default they "stringize" themselves in ISO 
8601 format at the specified precision (.1 second in this case).


SofaJpl is CLS compliant and therefore can be called by any CLS 
language, as shown by the C#, C++/CLI, and Visual Basic demonstration 
programs at the web page. The DLL was created primarily for personal use 
on my Windows system, but anyone can download it for free. A full 
installation is almost exactly 1 megabyte.

http://home.earthlink.net/~s543t-24dst/SofaJpl_NET/index.html


More information about the LEAPSECS mailing list