This post contains a list of misconceptions about date and time. The explainations are not exhaustive, sometimes it's just a counter-example.
#Everybody uses the same calendar
Not all countries have adopted the Gregorian calendar at the same time. France, Spain, Italy and a few other countries adopted the new calendar on 15 October 1582. British Empire changed in September 1752. Russia didn't switch until 1917. Greece is the last European country to make the change in 1923. According to Wikipedia, the last country to adopt the Gregorian calendar is Saufi Arabia in 2016.
Some cultures use different calendars based on lunar rather than solar cycles, or some combination of lunar and solar.
#1 year = 12 months
Some calendars use leap months, so a year can have 13 months. In the .NET BCL,
DateTimeFormat.GetMonthName accepts a value between 1 and 13. It's to accommodate calendar systems that have leap months, such as implemented by
EastAsianLunisolarCalendar classes. For instance, Hebrew calendar has Adar as its 6th month in a common year, which become Adar 1 and Adar 2 (months 6 and 7) in a Hebrew leap year.
The Ethopian calendar has 13 months.
The Wondrous calendar has 19 months and 4-5 intercalary days (which are not part of any of the 19 months).
#1 year = 365 days
#1 year = 365 or 366 days
There are various examples in the past where some countries changed their calendar. In this case, the year could be shorter. For example, Great Britain changed their calendar in 1752, and a few days are missing in September.
TZ=BST cal 09 1752
September 1752 Su Mo Tu We Th Fr Sa 1 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Another example is Samoa which changed its time zone in 2011. This year the Friday 30 December does non exist. As 2011 is not a leap year, there are only 364 days in the year. (
TimeZoneInfo.FindSystemTimeZoneById("Pacific/Apia").IsInvalidTime(new DateTime(2011, 12, 30)))
The Hebrew calendar is a lunar calendar. Lunar months are shorter than solar months. So, every few years they add an extra month. Thus, you end up with years shorter than 365 days by a bit, and then a year with an extra month pushing it up to 380-something.
#Days are consecutives
If you look at the calendar for BST in 1752, you can see that the days are not consecutive. It jumps from the 2nd of September to the 14th of September.
September 1752 Su Mo Tu We Th Fr Sa 1 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
There are many other examples. Each time a country changes its calendar, the days may not be consecutive.
#Leap years are every 4 years
The year must be evenly divisible by 4. If the year can also be evenly divided by 100, it is not a leap year. Unless the year is also evenly divisible by 400. Then it is a leap year.
- 1900 is not a leap year
- 2000 is a leap year
- 2020 is a leap year
#Anybody can implements leap years correctly
Microsoft Excel incorrectly assumes that the year 1900 is a leap year, and the reason for this bug is well explained in the documentation.
#GMT is the same as UTC
Coordinated Universal Time (UTC) is an international time scale recommended by the International Bureau of Weights and Measures (BIPM) as the legal basis for time.
Greenwich Mean Time (GMT) is a time zone, which is the mean solar time at the Royal Observatory in Greenwich, London. It corresponds to UT1, the solar time at 0° longitude.
The time difference between UTC and GMT lies in fractions of a second. Therefore, for common purposes, both the times are considered the same. But, the time difference is important for scientific purposes.
#Time zone offsets are always integer numbers of hours
Many time zones are not integer numbers of hours. For example, Newfoundland Daylight Time is UTC-2:30. Australian Central Western Standard Time is UTC+8:45.
#Time zone offsets are always integer numbers of minutes
There are many counter-examples in the past where the offset contains seconds:
Zone Asia/Kabul 4:36:48 LMT 1890 Zone Asia/Yerevan 2:58:00 LMT 1924 May 2 Zone Asia/Baku 3:19:24 LMT 1924 May 2 Zone America/Boise -7:44:49 LMT 1883 Nov 18 12:15:11 Zone Europe/Andorra 0:06:04 LMT 1901
#Time zone offsets are between -12 hours and +12 hours
Line Islands Time is UTC+14
#Past data never changed
Time zone data can be wrong and get fixed. So, past data can changed. An example is asia/shanghai: https://stackoverflow.com/a/6841479/2996339. You can download the tz data from here and search for "Changes to past timestamps" in the
NEWS file to get more examples.
#Days start at midnight
Historically, the day started at noon. The switch to midnight occurs between 1920 and 1930. This was useful for astronomers, who can record their observation on the same day. For example, if you observe a star at 11:59 PM, you can record it as the same day as the observation at 12:01 AM.
A day, in the rabbinic Hebrew calendar, runs from sunset (the start of "the evening") to the next sunset (source)
#Midnight is a valid time
In Chile, the daylight saving time starts at midnight. So, midnight is an invalid time this day.
2019-09-07 23:59:59 2019-09-08 01:00:00
#Holidays span an integer number of whole days
In the Jewish calendar, the day starts when the moon comes out. This means that holidays that most calendars write as "Wednesday" will actually start on Tuesday night, and last until Wednesday night.
#DateTime + Time zone represent a single point in time
Daylight saving time can shift the clock backwards, so it can represent two different moments.
#The same month has the same number of days in it everywhere
In Sweden, February 30th 1712 is valid. This date is only valid in Sweden.
#1 minute = 60 seconds
The earth's rotation period varies over time, caused by climatic and geological events. Typically, the variation is about a second every couple of years. Whenever the variation from atomic time grows too large, a correction of one second is inserted, called a leap second. This is done in such a way that the difference never exceeds 0.9 seconds. For instance, June 30th, 2012 11:59:60 PM is a valid time.
Before Windows Server 2016, the Microsoft Time Service was not aware of leap seconds, but relied on the external time service to take care of this. Windows is now aware of leap seconds.
#Days are 24 hours long
Japan observed daylight saving time in 1948-1951. However, they use a strategy that is quite different from other countries. They simply add an hour at the end of the day:
Saturday 23:58 Saturday 23:59 Saturday 24:00 (no change of date) Saturday 24:01 ... Saturday 24:58 Saturday 24:59 Sunday 00:00 Sunday 00:01
#A stopped clock is right twice a day
It can be right 3 times a day or only once because of DST
#Time zone = offset
A time zone is not only an offset. It has a name and provide a way to convert a UTC date to a civil date in that time zone. This means it needs to provide the calendar to use, a base offset from UTC and a set of rules to define when the offset changes (daylight savings time). A time zone is associated to a region of the world.
Note that names such as "PST" or "EST" are not time zones. They are abbreviations for half time zone. Indeed, these time zones only apply half of the year. Also, some abreviations are confusing. For instance, BST is used for both British Summer Time, British Standard Time (used between 1968 and 1971), and Bangladesh Standard Time. So, it is recommended to use IANA time zone names to avoid any confusion (e.g. Europe/London, Asia/Dhaka).
#A country has 1 timezone
A country can have multiple time zones. For instance, France has 12 (13 including its claim in Antarctica) time zones spanning from UTC-11 to UTC+12.
You can find the list of time zones per country on Wikipedia.
#Daylight savings time is always -1 or +1 hour
#Daylight savings time happens at the same time in every time zone
The daylight saving time in Chile starts at midnight. In america/toront, the daylight saving time starts at 2 am. In Europe/Paris, the daylight saving time starts the last Sunday of March. In America/Toronto, the daylight saving time starts the second Sunday of March.
#All time zones in a country observe Daylight savings time
In Canada, many time zones observe daylight savings time. But there are no Daylight Saving Time clock changes in Yukon (America/Creston).
#Weeks start on Monday
In Israel, the week starts on Sunday
#Weekend = Saturday and Sunday
Many countries use different rules for workweek and weekend. Here're a few examples:
- Canada: Saturday-Sunday
- Israel: Friday–Saturday
- Iran: Friday
- Nepal: Saturday
#Months are 28-31 day long
Of course, the previous example with BST on September 1752 is also valid.
#Years start on January, 1st
In Great Britain, before 1752, the legal years start on 25 March. Thus, for example, 24 March 1707 was immediately followed by 25 March 1708, while the day following 31 December 1708 was 1 January 1708.
In the Ethiopians calendar, years start on 11 or 12 September.
For other calendar, you can check this wikipedia page: New Year's Day
#There is a year 0
#Changes in time zones occur with long notice periods
Argentina giving a 11 days of notice of their decision to cancel daylight saving time for 2009/2010.
In 2011, Turkey gave a two weeks notice that it was delaying the DST transition.
In 2013, both Morocco gave less than a day's notice that they were changing their time zone rules.
In 2022, Chili gave a 1 month notice that it was changing its time zone rules. For companies using monthly updates, this can be tricky to implement (Interim guidance on 2022 time zone updates for Chile).
#DateTime.UtcNow increases monotonically
You can change the system time manually or using a NTP server. So,
DateTime.UtcNow <= DateTime.UtcNow can be false if the system time goes backward between both calls.
#If you display a datetime, you'll get the same year as the one stored in the DateTime object.
Some libraries allow to use a format string to specify how to display a date. Some libraries support more features. For instance, some libraries allow to distinguish between year (e.g.
yyyy) and year as ISO week (e.g.
YYYY). In this case, the year displayed may be different from the one stored in the DateTime object. For instance, 2022-01-02 is week 52 in year 2021. Hopeful recent libraries use very different letters to avoid any issue.
#Computing the number of days between 2 dates is simple
Because of time zones and calendar changes, computing the number of days between 2 dates may require some additional logic. How do you handle the case where days are missing such in September 1752 in BST, or december 30, 2011 in Pacific/Apia?
#32 bits is enough to store anything
When using a signed 32-bit integers, Unix timestamp allows to represent date until year 2038. Switch to 64-bit integers to avoid such limitation.
.NET had a performance issue every ~29 days in some benchmarks. This root cause of this difference is that the thread-pool implementation was using
Environment.TickCount, a signed 32-bit value.
#Storing date in UTC prevent all issues
If you want to schedule a meeting next year at 10AM in New York, you shoud not compute the UTC date and store it. Indeed, you cannot be sure that the rules for DST will not change before the meeting.
#Synchronizing time between machines is easy
Synchonizing time can be important in distributed systems. The Network Time Protocol (NTP) protocol allows to synchronize time between machines. There are multiple factors that can make it difficult to get an accurate time:
- The NTP server may not be accurate
- The network may be congestioned
- The network may not be symmetric (not the same number of hops for the request to the server as the number of hops for the response)
- The machine clock may not be accurate, so the machine clock drifts too quickly
These posts explain how Windows uses NTP to synchronize time: Accurate Time for Windows Server 2016 and Time accuracy improvements for Windows Server 2016.
If your application need to handle date and time, be sure to understand what are the requirements of your application. Most of the time, you can limit the scope of what is needed to support. For instance, does your application need to bother with leap seconds, or with historical dates far in the past, or multiple time zones? If you can reduce the scope, the implementation will be much simpler and you may not have to bother will all the details of date and time!
Do you have a question or a suggestion about this post? Contact me!