A Question of Time
Published:  5 September 2018

Time. It's simple, we all understand it or we think we do. But there was a time when no-one knew how long a year was until Pope Gregory XIII commissioned his astronomers to define the year length and we inherited the leap year and the leap century as of October 1582.

In the modern era, computer time is the number of seconds from epoch isn't it? It is based on UNIX time. We all get that but it is about as simple as the calendar was 1000 years ago. UNIX time, UTC and GPS time are not the same thing and converting from one to the other is not always simple matter.

UNIX time

With a UNIX or Linux operating system the default time base is UNIX Time and is defined as the number of seconds after the UNIX epoch which is midnight on 1 January 1970.

Sounds simple, doesn't it.

It is relatively easy to work out the number of days since Epoch and multiply this by 86400 to get the number of seconds, store the value in a variable somewhere and then increment this number by 1 every 1000 milliseconds. It's been done this way for so long that there even is a special C type - time_t - for manipulating this value.

The Year 2038 problem

You may remember the Y2K problem, unless you are younger than GenY. For several reasons the year (called Year) value in a lot of real time clocks was only stored as two digits instead of four. So the year was due to click over from 99 -> 00 and there was a serious amount of work done testing computers and other devices with a 'clock' to check that the year 2000 was not going start with a lot of failing computer systems.

Despite all the naysayers in the world's press, it was a serious problem and a few spectacular failures included a lot of the radar systems at US airports that had not been updated.

Well ... there is another problem on the horizon. Originally the time_t type was a signed 32 bit integer value with a range from –2,147,483,648 to 2,147,483,647. Guess what happens when you add 1 to a signed 32 bit integer with a value of 2,147,483,647 (which represents 03:14:07 UTC on 19 January 2038)? Yep. The value rolls over to –2,147,483,648. A time value sometime in 13 December 1901.

This is not good - especially if your industrial controller is using a timestamped security certificate to sign command and control communications.

But 2038 is 20 years away, I hear you cry. True: but industrial controllers have a lifetime of 15 to 25 years and often they only reach end of life when spares become difficult to source. There was a lot hardware developed in the late 1970's that was still in use in 1999 and was subject to the Y2K problem. So, many control systems being installed now will still be in use in 2038.

The 2038 problem can be addressed by using a 64-bit operating system which changes the time_t type to be a signed 64 bit integer - thus pushing the issue out until 15:30:08 UTC on Sunday, 4 December 292,277,026,596 which is a little bit further in the future.

If you are designing embedded systems with an expected long lifetime that rely on a real time clock, it is good advice to pay attention to the way you define the time_t variable (or its equivalent). Many embedded microprocessors are only 8 bit and dealing with 64 bit numbers in an 8 bit system takes a bit of thought and more than a bit of skill.

UTC

UTC stands for Universal Time Coordinated. The name is a compromise between French and English and was chosen to minimize confusion between languages. UTC is a Time Standard, not a Time Zone, and the concept was formalized in 1960 with the name UTC being adopted in 1967.

Until 1972 Greenwich Mean Time (GMT) was the same as Universial Time (UT) (also known as Zulu Time) - the basis of the time zone system used today that was created in 1884.

In 1972 UTC replaced GMT as the worldwide Time Standard. GMT is now a Time Zone used by the United Kingdom in winter and some other countries that lie on or near the Prime Meridian.

We could be forgiven for assuming UTC and UNIX time are the same. Well, not exactly. GMT was based on the sun being perfectly overhead along the Greenwich Meridian, the longitude zero degrees line which runs from the north pole to the south pole directly through Greenwich.

There are two problems with this:

  1. a solar day (the time the sun takes to go from noon today to noon tomorrow) is not exactly 86400 seconds - at the moment it's about 86400.002 seconds with some very slight variation from day to day.
  2. the earth's rotation is (ever so slightly) slowing down - so the length of a day is very slowly getting longer. Also, the Earths orbit tends to wobble around a tiny bit owing to very complex interractions with different heavenly bodies including the moon and the larger planets such as Jupiter, plus the fact that the Earth is not exactly a sphere.

To keep UTC in sync with the solar day, every so often astronomers insert a leap second into UTC to ensure that the sun still appears directly overhead at midday at Greenwich.

This adds the following 'wriggles' to time-keeping:

  1. when a leap second is added to UTC, that particular minute has 61 seconds (and your program code has to be able to deal with a minute that is 61 seconds long).
  2. There are a few seconds difference between the calculated Unix Time (in seconds from 1/1/1970) and the number of UTC seconds since 1/1/1970. Yep, Unix Time simply skips back a second every time there is an insertion of a leap second into UTC.
  3. UTC in its current form using whole leap seconds was only formalized in 1972. Before 1972 fractional leap seconds were inserted as required. This makes doing some forms of time calculations inexact, in fact, to be honest, damned infuriating.

Arrrggggghhh. (infuriated noise)

So why not use GPS time? It's based on Atomic clocks and should be accurate. Shouldn't it?

GPS time (Global Positioning Time)

GPS engines providing timestamp data with a resolution of a second are now commonplace and cheap. In fact, there are GPS engines built into the WP8548 and WP77xx modules and the underlying operating system on these modules can be made to use the time information from the global positioning system to set the local clock.

But we have another problem. GPS time is synchonised to UTC, so GPS time is also subject to the addition of leap seconds and thus the same issues described above for UTC arise. Also, the GPS epoch is 6 Jan 1980 UTC and there are 19 seconds of difference between Unix Time (seconds) and GPS time at the GPS epoch.

This can become a real problem for modern control systems. Rio Tinto and BHP both use remote control centres in Perth (Western Australia) to control not only several mine sites but also a few railway lines linking the mines to the ports. Thus you have hundreds of programmable logic controllers, plant historians, control databases, operator display screens, SCADA systems and engineering workstations that are interconnected. The engineers may be carrying out complex diagnostics using time and developing dynamic system models for model-predictive control. If any of the computer clocks are out of synchronism you could be heading for an expensive or dangerous out-of-synch collision between say, a driverless train and a set of crossing gates. Nineteen seconds is a long time at a level crossing.

TAI

TAI stands for Temps Atomique International which translates from the French as International Atomic Time. This is now the world's standard reference time.

TAI is calculated from the average of a number of atomic clocks around the world and was formalized in 1971 as exactly 86400 SI (standard international) seconds per day with no leap seconds.

According to Dan Berstein, TAI times are identified by year, month, day, hours, minutes and seconds. TAI was synchronised with the predecessor to UTC at the beginning of 1958 so TAI and UTC have been slowly diverging ever since.

TAI is not generally used directly in a LINUX system - although there are libraries becoming available that are based on TAI rather than UNIX time.

So what do I do?

As an engineer working with Internet of Things (IoT) applications, possibly the most important issue is to make sure that your IoT devices in the field are using the same timekeeping methodology as the (cloud) server that you are sending your data to.

Second, the method of representing the time when sending time-stamped/time series data to your server is important. Don't be tempted to save a few bytes by sending the Unix time up to the server - use an unambiguous, standard time representation such as that described in ISO8601.

Third, make sure that all your IoT devices use the same time source - be it GPS time, NITZ (Network Information and Time Zone) data from the cellular provider, NTP from the internet or some other common source - try not to mix and match between sources if you can avoid it. After all, as the old proverb goes:

A man with one watch knows the time, a man with two watches doesn't...

References

UTC, TAI, and UNIX time

Y2038 problem

About UTC

Unix time and relation to UTC

History of TAI

Tables of epoch offsets

ISO8601 overview