# Solution: Leap seconds aware timezone + time synchronization

## kab-el

For the past two days I was reading about solutions of leap seconds problem, and I came with an easy solution for Gentoo.

UNIX time is not continuious

When a leap second occurs, there is a discontinuity in UNIX timestamp to keep it in line with UTC, for example:

```
TAI                      UTC                      Unix time

1999-01-01T00:00:29.75   1998-12-31T23:59:58.75   915 148 798.75

1999-01-01T00:00:30.00   1998-12-31T23:59:59.00   915 148 799.00

1999-01-01T00:00:30.25   1998-12-31T23:59:59.25   915 148 799.25

1999-01-01T00:00:30.50   1998-12-31T23:59:59.50   915 148 799.50

1999-01-01T00:00:30.75   1998-12-31T23:59:59.75   915 148 799.75

1999-01-01T00:00:31.00   1998-12-31T23:59:60.00   915 148 800.00

1999-01-01T00:00:31.25   1998-12-31T23:59:60.25   915 148 800.25

1999-01-01T00:00:31.50   1998-12-31T23:59:60.50   915 148 800.50

1999-01-01T00:00:31.75   1998-12-31T23:59:60.75   915 148 800.75

1999-01-01T00:00:32.00   1999-01-01T00:00:00.00   915 148 800.00

1999-01-01T00:00:32.25   1999-01-01T00:00:00.25   915 148 800.25

1999-01-01T00:00:32.50   1999-01-01T00:00:00.50   915 148 800.50

1999-01-01T00:00:32.75   1999-01-01T00:00:00.75   915 148 800.75

1999-01-01T00:00:33.00   1999-01-01T00:00:01.00   915 148 801.00

1999-01-01T00:00:33.25   1999-01-01T00:00:01.25   915 148 801.25

```

As you can see, the 915 148 800.00 second is there 2×. This discontinuity can reflect on your system clock by stopping time for a second or instantly going one second back (The first one, which stops your system time for a second, occurs when your kernel is aware of leap seconds existence and NTP synchronizer tells it beforehand that a leap second will occur. The second one happens when you have a historic kernel which is not aware of leap seconds and NTP synchronizes time and when the synchronisation occurs, your time will update by -1 (or +1, but leap second deletion didn't occur in 40 years of leap seconds usage).)

Because of this there are points in time that are not encodable into Unix time, and there may be (but aren't, because leap second deletion didn't occur yeat) UNIX times, which do not correspond to any moment in time.

Google's solution

Google solved this by creating a leap smear, which means that when their time server discovers that there will be a leap second, it will slow/speed up time a little so that the one leap second will be distributed into bigger time interval (for example a month) and there will therefore be no discontinuity. Although this solution is nice and serves good, there is another, for me more interesting one.

Let's make UNIX time right, by breaking compatibility with POSIX a little  :Smile: 

Instead of creating a leap smear or corrupting system clock flow, this solution changes UNIX time definition a little: Let it be number of seconds that have elapsed since 00:00:00 UTC, Thursday, 1 January 1970, counting leap seconds. This way your time() system call will return a value by 25 seconds greater (as of January 2014) than other systems using NTP synchronization, but your system won't need leap seconds adjustments, which create discontinuity.

The sys-libs/timezone-data package provides timezones which are leap seconds aware, so conversion from your timestamp to human readable time will give correct results. To distinguish between a leap seconds aware and a leap seconds not aware timezone, there is a timezone name prefix "posix/" and "right/", respectively. For example "posix/Europe/Zurich" is a leap seconds not aware timezone, and "right/Europe/Zurich" is leap seconds aware. By omitting this prefix the default behaviour takes over, which is posix, and therefore leap seconds not aware.

We want the default behaviour be the "right/" behaviour (the files in /usr/share/zoneinfo be equivalent to those in /usr/share/zoneinfo/right, instead of /usr/share/zoneinfo/posix). To do this automatically on sys-libs/timezone-data installation I created a postsync.d script, which updates sys-apps/timezone-data ebuilds so they will install "right/" timezone files as default.

Put this into /etc/portage/postsync.d/timezone-data:

```
#!/bin/sh

tmp=`tempfile`

for i in /usr/portage/sys-libs/timezone-data/*.ebuild; do

        if ! grep -e right_posix $i >/dev/null; then

                sed -e 's/emake install/emake install REDO="right_posix"/' $i >$tmp

                cat $tmp >$i

        fi

done

rm $tmp

ebuild `ls /usr/portage/sys-libs/timezone-data/*.ebuild | head -n 1` manifest

```

and then run

```
$ emerge --sync && emerge -1 sys-libs/timezone-data
```

What we want now is time synchronization that synchronizes time not to UTC but to our right UNIX time, which is leap seconds aware. Forget net-misc/ntp, it cannot do this, I even browsed the code and didn't find anything. The only solution that could work with NTP would be a NTP server that uses this right UNIX timestamp, but all official NTP servers are UTC. (Although you can then make this solution a NTP server and synchronize other computers in your network via NTP.) Fortunately there is a tiny utility that can synchronize time from a NTP server and correct leap seconds count from your timezone-data database.

Run

```
$ emerge net-misc/openrdate
```

edit /etc/conf.d/openrdate to

```
RDATE_SERVER="0.gentoo.pool.ntp.org"

OPENRDATE_OPTS="-n -c"
```

then run

```
$ rc-update add openrdate boot
```

to synchronize on boot time and add this line to root's crontab:

```
0 * * * * /usr/bin/openrdate -s -c -n 0.gentoo.pool.ntp.org
```

to synchronize periodically (every hour, in this case).

And voala, you now have a system which cannot be corrupted by a leap second. I hope.

Disadvantages

Unfortunately not all software supports leap seconds aware timezones, for example PostgreSQL won't even start if it is configured to use a "right/" timezone. Because we made the default timezone files "right/", we have to configure PostgreSQL to use a "posix/" timezone. Edit /etc/postgresql-9.3/postgresql.conf

```
...

log_timezone = 'posix/Europe/Zurich'

...

timezone = 'posix/Europe/Zurich'

...
```

This will of course lead to PostgreSQL reporting time 25 seconds off (as of January 2014). Maybe PostgreSQL will support leap seconds aware timezones in a future version.

----------

## 666threesixes666

what a horrible idea.  your clock could be as far as 24 hours off or anywhere in between.  everyone thinks its noon, year after leap thinks its 6pm instead.

----------

## Akkara

Interesting idea, kab-el.  Welcome to the forums!

And 666threesixes666: care to elaborate how the clocks could end up 6 hours off?  Please ensure you understand the idea and provide a clear example explaining how the problem might come about, if you think something was overlooked.

Chiming in with inflamatory assertions without showing the evidence in a constructive manner does not help anybody.

----------

## 666threesixes666

from what i gathered....  a year is 365.25 days long, and the box would display it as that...  not just 6 hours off, 6 for year 1, 12 for year 2 18 for year 3 and 24 for year 4 thus adding the extra day for leap year.

----------

## NeddySeagoon

666threesixes666,

Leap years and leap seconds are not really related.

A year is not 365.25 days.  Its close but years exactly divisible by 400 (like 2000) are not leap years.

Leap seconds keep astronomical time correct and are related to the rotation of the earth on its axis, around the sun an the precession of the equinoxes. 

The first question is do we care if UNIX time and  astronomical time slowly diverge?

Over the course of a lifetime, its not important to me ... it will only be a few seconds.

Its more important that we all agree a standard and use it.

Of course astronomical time is important to astronomers.  Like it or not, its coming into daily use to.

GPS and friends use astronomical time (corrected for the relativistic effects of the satallites motion)

We either need to convert between UNIX time and astronomical time or standarise on astronomical time.

The latter makes life easier for all, so its discrete leap seconds, or leap second smearing.

I prefer the former, but its a question of standards.

kab-el is mistaken in one detail.  UNIX time is always monotonic. Even with leap seconds, it never goes backwards.

The wonderful thing about standards is that there are so many to choose from :)

----------

## kab-el

666threesixes666,

as NeddySeagoon wrote, leap seconds have nothing to do with leap years. We use a leap year, as you said, because a year does not have exactly 365 days. Leap seconds are somtimes added or (till yet never) removed because tidal forces and other factors change Earth's rotation speed a little. Read the Wikipedia article on leap seconds.

NeddySeagoon,

Firstly, a small mistake on leap years: Every year which is divisible by 4 is a leap year, but every year divisible by 100 is not (although it is divisible by 4), but every year divisible by 400 is a leap year. 2000 was a leap year, 2100 won't be. To conclude:

```
is_leap_year = ((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0
```

Secondly, UNIX time is not monotonic. The definition of UNIX time is as follows: the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, not counting leap seconds. From Wikipedia: due to its handling of leap seconds, it is neither a linear representation of time nor a true representation of UTC.

Read http://www.wired.com/wiredenterprise/2012/07/leap-second-bug-wreaks-havoc-with-java-linux/

Currently a NTP synchronized Linux kernel handles leap seconds by stopping the CLOCK_REALTIME time when a leap second is added (by that I mean that for one second, CLOCK_REALTIME clock would not increment) or skipping one second when a leap second is removed (but as I mentioned, this has never occured yet). Previously it was done by simply substracting or adding 1 second from/to the counter, but that is exactly what caused the havoc on reddit and other servers - an application did something exactly at that point and an event mismatch occured - event A, which should have occured before event B, reported that it occured after event B, because just before event B occured, the time counter skipped a second into past.

The fact that glibc supports timezones with leap seconds and that sys-libs/timezone-data install timezones with leap second information and that openrdate can do leap second correction means that the system is ready for this altered definition of UNIX time, it is just not used and, unfortunately, not all software supports it (PostgreSQL for example).

----------

## PaulBredbury

 *kab-el wrote:*   

> openrdate -s -c -n 0.gentoo.pool.ntp.org

 

Is that command guaranteed to never cause "the clock" to jump to an earlier time?

Since time moving backwards is presumably what triggered the bug on the servers. As opposed to time standing still, or moving slowly forwards.

----------

## sla29970

This idea was presented at the first Future of UTC meeting in 2011, and the problems faced by Linux kernels were documented at the second meeting in 2013.  See http://futureofutc.org/ for the full conference proceedings, and see http://www.ucolick.org/~sla/leapsecs/right+gps.html for more about the code that can test this idea.

----------

## kab-el

 *PaulBredbury wrote:*   

>  *kab-el wrote:*   openrdate -s -c -n 0.gentoo.pool.ntp.org 
> 
> Is that command guaranteed to never cause "the clock" to jump to an earlier time?
> 
> Since time moving backwards is presumably what triggered the bug on the servers. As opposed to time standing still, or moving slowly forwards.

 

You are right, openrdate uses settimeofday by default (which does a time step) and it needs -a flag to use adjtime (which slows down or speeds up the system clock for a while). When the system is booting it is good to step to a right time and from then on only adjust.

I have written a small POSIX timestamp compatibility library for glibc/linux systems which use right timestamp on system clock.

By executing a program with LD_PRELOAD=/path/to/time2posix.so environment variable the program can still use a 'posix/' timezone and display system time correctly (system calls for getting/setting system time are patched byt time2posix.so).

With this library I can use ntpd to keep the time synchronized and also use kernel time synchronizing mechanisms without needing to patch ntp.

See https://github.com/elkablo/time2posix

----------

## aevertett

I have read that many are advocating the abolition of leap-seconds mainly because of the issues of accounting for them in computer and telecommunications systems. I work with NTP a fair bit and leap seconds and GPS time can be a real headache!

Ev.

----------

## steveL

 *NeddySeagoon wrote:*   

> The first question is do we care if UNIX time and  astronomical time slowly diverge?
> 
> Over the course of a lifetime, its not important to me ... it will only be a few seconds.
> 
> Its more important that we all agree a standard and use it.
> ...

 

I agree we should just standardise on astronomical time, and be done.

I have no opinion on which method is better: I'd go with your call.

 *Quote:*   

> kab-el is mistaken in one detail.  UNIX time is always monotonic. Even with leap seconds, it never goes backwards.

 

Well the OS should never let time go backwards, but it's perfectly possible for the admin to set the clock time back, and mess up automated processes like make.

POSIX has had a CLOCK_MONOTONIC since about 1994 (POSIX.4 iirc) for this reason (vs CLOCK_REALTIME meaning user wall-clock time, not a realtime clock; it can go backwards/be set by user.)

The GPS thing is interesting, though.

----------

