# Why does the TimeObject seem to lose precision? (+ note on units)

According to the documentation (11.0.1.0)

Shorter lists can be used in TimeObject[{h,m,s}], which represents the time to whatever accuracy is specified: {h} is not [sic?*] treated as being equivalent to {h,0,0}.

and

Subtracting two TimeObject constructs yields a time quantity.

However, although a TimeObject can certainly contain high accuracy times, subtraction is not giving me the result I expect.

t1 = TimeObject[List[0, 0, 1.*^-9]];
t2 = TimeObject[List[0, 0, 2.*^-9]];
ns = Quantity[1, "Nanoseconds"];
Print@Column[{t1  // FullForm , t2 - t1 // FullForm, t2 - ns // FullForm}];

TimeObject[List[0,0,1.*^-9],Rule[TimeZone,2.]]
Quantity[0,"Seconds"]
TimeObject[List[0,0,0.],Rule[TimeZone,2.]]


We see above that the t1 indeed represents 1ns but the difference of t1 and t2, and t2 - 1ns, which should be both be 1 ns in different forms, is given as 0s.

Note also that AbsoluteTime[t1] does not show the nanosecond, but AbsoluteTime[{1900, 1, 1, 0, 0, 1.*^-9}] does.

Questions: Are these behaviours to be expected? I have high precision date & times stamped data in a file and need to obtain the differences to high precision; I have been importing the timestamps from CSV to DateObjects and differencing is failing - what should I be doing?

* is that really a typo in the documentation?

TimeObject[{1}] - TimeObject[{0, 30}]


works as one would expect if the word "not" is omitted.

PS For the benefit of others who are new to working with units in MMA and might be caught out as I was in the beginning, all MMA units are named in the plural - and capitalised (as is standard for MMA defined symbols, even though unit names are always provided as string values) - e.g. "Seconds", even though MMA says it supports all the units defined by NIST Special Publication 811, where all units are named in the (lower case) singular e.g. "second" - as seems more appropriate for something called a unit.

The problem here is the combination of a) the definitions for t1 and t2 give the seconds as machine precision numbers, and b) the internal computations are performed in AbsoluteTime form (i.e. number of seconds since the beginning of Jan 1st 1900). This combination makes computations to be performed in machine precision, whose approximately 16 digits cannot contain information on nanoseconds: Today corresponds to 3.76*^9 seconds, so a machine precision date in absolute form can only store information for about 6 or 7 more digits, not the 9 needed for nanoseconds. That also explains why there are no problems in the computation if taking the year to be 1900 instead of something in the 21st century.

The correct way to handle this is to start with values for t1 and t2 that are either exact or contain higher precision numbers. For example, take exact values:

t1 = TimeObject[List[0, 0, 10^-9]];
t2 = TimeObject[List[0, 0, 2 10^-9]];

t2 - t1
(* Quantity[1.*10^-9, "Seconds"] *)


or take definitions with numbers having accuracy (number of decimal places to the right of the decimal point) of 12 digits for example (that's denoted with the double backtick):

t1 = TimeObject[List[0, 0, 1.12*^-9]];
t2 = TimeObject[List[0, 0, 2.12*^-9]];

t2 - t1
(* Quantity[1.*10^-9, "Seconds"] *)
`

In both cases the results are being returned with machine precision, but they should have kept the accuracy of the inputs. That's something to fix.