Happy extra rare new year

In the 21st century there are only 11 new years that start with a monday. This year is the third of them. That makes it rare.

I attempt to publish a blog post every Monday, and years starting with Monday are rare. The next time when this happens it will be the year 2029.

This year is extra rare because it's 11 years apart from the adjacent calendar years that start with a Monday, and it's the first one in this century that is 11 years apart. The other years like this will be 2046 and 2074. Those are the only ones in this century.

Note that this not going to make this year different from the other years. It is only different in the calendar. And only if you care about mondays.

Perhaps you would expect something special to be archived to the beginning of this year. For example, how to calculate the day, weekday, week and month of the calendar.

There wouldn't be a better day than today to study the relationship between computers and time and discuss the big ideas in measuring time with computers.

Doomsday rule

The doomsday for this year is Wednesday. Using a doomsday rule you can determine weekday from the date.

Doomsdays are the days in the calendar that share the same weekday with the last day of the february. To calculate a doomsday for the year you can use the following formula:

y = year
tuesday = 2
doomsday = (tuesday + 5 * (y % 4) + 4 * (y % 100) + 6 * (y % 400)) % 7

The leap year determines whether there will be 29 or 28 in the february. It occurs every 4 years, except that it is skipped every 100 years unless the year is divisible by 400.

is_leapyear = y % 4 == 0 and (y % 100 != 0 or y % 400 == 0)

Using this, you can use the following table to find doomsdays in a year:

For common years:
January  3, 10, 17, 24, 31 1–5
February 7, 14, 21, 28     6–9

For leap years:
January  4, 11, 18, 25    1–4
February 1, 8, 15, 22, 29 5–9

For both:
March     7, 14, 21, 28     10–13
April     4, 11, 18, 25     14–17
May       2, 9, 16, 23, 30  18–22
June      6, 13, 20, 27     23–26
July      4, 11, 18, 25     27–30
August    1, 8, 15, 22, 29  31–35
September 5, 12, 19, 26     36–39
October   3, 10, 17, 24, 31 40–44
November  7, 14, 21, 28     45–48
December  5, 12, 19, 26     49–52

The first column describes the month, the last column describes the week span, in the middle there are doomsday days of that month.

All this information is available in wikipedia, but I put it here just in case.

You can determine the weekday by finding the nearest doomsday from the above table and calculating the modulus.

Problems in timing events

Few people have to know that time elapses at different rate relative to where you are. The time dilation effect has been measurable with modern equiment for decades.

This is a problem for accuracy of measurements that span long time periods.

Time on a computer

In a computer the dates and times are represented as seconds passed since an epoch. For example POSIX standard determines the epoch to start from the midnight of January 1, 1970.

The standard specifies that you can deduce the number of days since the epoch by dividing the timestamp by 86400. Specifically the standard allows a well-defined conversion between a Gregorian calendar time and seconds elapsed.

The POSIX standard specifies a relationship between the calendar and timestamps, in the section 4.16.

You can calculate the Unix timestamp for your year with this formula:

tm_year = 2018 - 1900
timestamp = ((tm_year-70)*31536000
    + ((tm_year-69)//4)*86400
    - ((tm_year-1)//100)*86400
    + ((tm_year+299)//400)*86400)

The first line calculates the approximate timestamp, the remaining three lines adjusts the timestamp for leap years.

Likewise you can calculate a year from the timestamp by guessing the year and then adjusting your guess until you get it right:

days = timestamp // 86400
tm_year = (days // 365) + 70
leaps = (tm_year-69)//4 - (tm_year-1)//100 + (tm_year+299)//400
p_year = 0
while tm_year != p_year:
    p_year = tm_year
    tm_year = (days - leaps) // 365 + 70
    leaps = (tm_year-69)//4 - (tm_year-1)//100 + (tm_year+299)//400
tm_yday = (days - leaps) % 365
year = tm_year + 1900

You can use the ideas from the doomsday rule to convert the year of the day to a calendar day.

This kind of approach treats the calendar as an inconvenient measurement stick.

But what about leap seconds? You may have heard of them.

The above code conveniently ignores leap seconds, they do not exist in our measurement stick. And the stick measures seconds since an epoch.

A second

The written notions of the time are still bound to the orientation of the solar system. It used to be that there were 86400 seconds in a day. The length of a second varied by Earth's rotation rate.

Not having a constant second limits the accuracy of measurements of changing variables such as position or temperature difference.

The modern SI standard defines the second as "the duration of 9192631770 periods of the radiation corresponding to the transition between the two hyperfine levels of the ground state of the caesium 133 atom."

The second is defined by the most accurate time tracking element we know to this day. An atomic clock.

We still have a time standard based on Earth's rotation called Universal Time, though.

International Atomic Time

During the last century people set up atomic clocks to track time. This formed the International Atomic Time. Those clocks tick and measure seconds passed since 1972.

Since the calendar display is a function over the elapsed seconds, the TAI can be also displayed as a calendar date.

Coordinated universal time

Earth has turned out to be a crappy clock. The average length of a solar day is about 86400.002 seconds.

To keep the calendar match the seasons, the calendars use coordinated universal time abbreviated UTC. As of 31 December 2016, the UTC has been 37 seconds behind TAI.

Some UTC days are longer by one second.

Leap seconds are not good for your computer

Stupid people do not need to time up events with an accuracy of a second. Most computer clocks are just moved to match the UTC time when a leap second happens.

On computers leap seconds cause havoc. This is because logs and databases depend on timestamps being monotonically increasing.

So when you write into a log or a database you would prefer that the 'now' timestamp increases monotonically. It would be nice if you could mark it as a hardware failure if the clock no longer behaves consistently.

Thanks to UTC daylight saving time for computers, there will be moments when the timestamp doesn't grow monotonically. Sometimes they jump as much as a second behind, and that should be 'ok' for whoever makes the system to work.

An easy fix

It has been argued that the leap seconds should be removed from the UTC due to the problems they expose.

The leap seconds are only a problem because we want the displayed time to approximate universal time. We want to do that because our tracking of time is seasonal.

But if we wanted to remove leap seconds, why not drop all seasonality from system time, including the gregorian calendar?

Today would be the day 17532, or alternatively the day 2018¤12. Few people are ready for stardates yet though. The seasonality is there for a reason.

I wonder how people did not notice that we have had a solution to seasonality since railways and telegraphy? We've used time zones since forever to customize the time displays.

You could synchronize your computer clock directly from the TAI time that is independent from the UTC, then for every UTC year you denote how many seconds it is drifting from the TAI.

The computer time is in the TAI, and you use an API to convert it to UTC for display. You would include the TAI in the timezone offset.

To summarize here's a proposition to solve problems created by leap seconds:

  1. Synchronize your computer system clock directly from the TAI time.
  2. For every UTC year, record how many seconds it is drifting from the TAI.
  3. Apply the TAI difference in same places where you apply the timezone.

The display system might still crash due to a leap second, but that isn't as bad problem as the crashing of a database.