Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How precise should I encode a Unix Time?

I came across this because I am working with time across multiple platforms and seems like they all differ a little bit from each other in how unix time is implemented and/or handled in their system. Thus the question.

Quoting Wikipedia page on Unix Time:

Unix has no tradition of directly representing non-integer Unix time numbers as binary fractions. Instead, times with sub-second precision are represented using composite data types that consist of two integers, the first being a time_t (the integral part of the Unix time), and the second being the fractional part of the time number in millionths (in struct timeval) or billionths (in struct timespec). These structures provide a decimal-based fixed-point data format, which is useful for some applications, and trivial to convert for others.

Which seems to be the implemention in Go (UnixNano). However, in practice, there are many languages/platforms which use milliseconds (Java?) and also some platforms uses Float (to try to maintain some precision) and others mostly uses Int.


So if I'm implementing a transport format and I only have exactly 64 bits available to store a time value and no more, my question is two-fold:

  • Should I encode it as an integer or a floating-point value? And
  • Should I use seconds, milliseconds or nanosecond precision?

The main goal being to try to be as accurate as possible across as many languages and platforms as possible (without resorting to custom code in every single platform, of course).


p.s. I know this is a little subjective but I believe it's still possible to make a good, objective answer. Feel free to close if that's not the case.

like image 844
chakrit Avatar asked May 14 '19 09:05

chakrit


People also ask

How precise is Unix timestamp?

Unix time is not a true representation of UTC, because leap seconds are not independently represented. Instead, every day in Unix time contains exactly 86400 seconds, with leap seconds sharing the same timestamp as the second immediately before or after them.

Is Unix time in milliseconds or seconds?

Unix is an operating system originally developed in the 1960s. Unix time is a way of representing a timestamp by representing the time as the number of seconds since January 1st, 1970 at 00:00:00 UTC.

What is the resolution of Unix time?

Pitfall 2: ResolutionUNIX timestamps are usually represented as seconds. However most operating systems have much higher resolution than this. If you need higher resolution than one second, you will probably need to use an extended timestamp which contains a decimal portion that corresponds to fractional seconds.

How many bits is Unix time?

UNIX data represents different points in time as signed integers, traditionally of 32 bits, by encoding the UNIX timestamp. Because it uses 32 bits, UNIX time can only cover approximately 136 years in total.


2 Answers

It depends on what the required precision of the time value is, and its maximal range.

When storing nanoseconds in an unsigned 64bit integer, the range is about 584 years (2^64 ns), so precise and long enough for any practical application already.

Using a floating point format has the advantage that both very small and very large values can be stored, with higher absolute precision for smaller values. But with 64bit it this probably not a problem anyways.


If the time value is an absolute point in time instead of duration, the transform format would also need to define what date/time the value 0 stands for. (i.e. the Epoch)

Getting the current time on a UNIX-like system can be done using gettimeofday(), for example, which returns a struct with a seconds and microseconds value. This can then be converted into a single 64bit integer giving a value in microseconds. The Epoch for UNIX time is 1 January 1970 00:00:00 UT. (The clock() function does not measure real time, but instead the duration of time that the processor was active.)

When a time value for the same transport format is generated on another platform (for example Windows with GetSystemTime(), it would need to be converted to the same unit and epoch.


So the following things would need to be fixed for a transport protocol:

  • The unit of the time value (ms, us, ...), depending on required precision and range
  • If the time is a time point and not a duration, the Epoch (date and time of value 0)
  • Whether it is stored in an integer (unsigned or signed, if it is a duration that can be negative), or as a floating point
  • The endianess of the 64bit value
  • If floating point is used, the format of the floating point value (normally IEEE 754)

Because different platforms have different APIs to get the current time, probably it would always need some code to properly convert the time value, but this is trivial.

like image 195
tmlen Avatar answered Sep 24 '22 17:09

tmlen


For maximum portability and accuracy, you should probably go with a type specified by POSIX. That way, the code will be portable across all Unixes and other operating systems conforming to POSIX.

I suggest that you use clock_t and the clock() function for time. This has a variety of uses, including measuring time and distance between one point in a program and another. Just make sure to cast the result to a double and divide by CLOCKS_PER_SEC afterwards to convert that time into a human-readable format.

So, to answer your question:

  1. Use both an integer and a floating-point value
  2. Unsure precision (the number of clock cycles between calls) but accurate enough for all non-critical applications and some more important ones
like image 36
S.S. Anne Avatar answered Sep 23 '22 17:09

S.S. Anne