Was 1900 a leap year and does every minute have 60 seconds?
In Java we have a new API for Date and Time since Java SE 8. Before that, there was already an API with mutable dates and fore some reason there was a date just for SQL.
Many were not happy with the old API. There was Joda-Time, which later became the basis for JSR-310 and is now found in the package “java.time”.
A lot of confusion comes from the ambiguity of some terms. What is “time”? A point in time? As in 12:15? Or does it include a day? Like “Tomorrow, at 12:15”? But which time zone? Or is it the duration? When you use a stop watch you get something like 12 minutes and 40 seconds.
Here I list some mistakes you’d probably make when you implement it yourself and possibly even if you use an API. Maybe the API doesn’t actually handle the problem or you are not using it correctly.
Leap Years
You can’t just use year % 4 == 0. that’s not how this works. The Gregorian calendar has a clear definition on leap years so use isLeap().
The Gregorian calendar only exists since 1582
If you need dates before that you are in trouble. You could just use the same system and apply it to the time before that calendar even existed. But then the calendar that was actually used back then would have completely different dates for the ones you are using.
Some calendars have a year 0 and others don’t. What was before year 1? It could be year -1 or 0. This depends on the calendar.
Different APIs and customs
Some APIs use 0 for January, others use 1. Some even give you 119 for the year 2019, because they always subtract 1900 from the year. Always read the documentation carefully.
And then there are cultural differences. Such as the beginning of the week. Is it Monday or Sunday? Computer systems mostly use timestamps. But Humans like the weirdest representations of dates. YY/MM/DD
which shortens the year and MM/DD/YYYY
which is in an order that just makes no sense.
Time is relative
Time dilation probably won’t matter unless you work for a space agencies like NASA or ISRO. Just remember that you always only use time at earth. And on this planet we have time zones. If you have a website and you want to know when a comment was posted you can just store the UTC time and only when displaying it to users you use their local time zone. You can’t store “2018-02-21T12:15:35” in the database. You have to convert it to UTC first or store it with the time zone: “2018-02-21T12:15:35+01:00”.
But this is not how the database would store it. It’s not a string. The database will know how to optimize this and use as little space as possible. This way you also know the time zone and you can tell what the local time was when the event happened.
However, time zones change as they are arbitrary and depend on politics. And then there is daylight saving time. Only some countries have that and they don’t change all at the same date.
A Minute is not always a Minute
There are leap seconds. Sometimes they have to add or take a second and then that minute is not 60 seconds long. Just as a year is not always 365 days long.
Leap seconds are quite a problem if you need to have exact records of time. Some APIs don’t even support them and others don’t enable them by default because this is often causing more problems that it solves. And if they support leap seconds it might be by some “trick” to avoid problems.
You can read the javadoc of Instant to get more information. Here’s just one bit of it:
On days that do have a leap second, the leap second is spread equally over the last 1000 seconds of the day, maintaining the appearance of exactly 86400 seconds per day.
Documentation on classjava.time.Instant
There is a physical definition of what a second is, but due to such trickery and because of synchronization of our clocks you can’t just use the seconds of the clock.
So there’s a second reason why a second could be shorter or longer. The system clock needs to be synchronized. If you get the time of the system clock and then again a second later you don’t necessarily have a difference of one second because the system might have used Network Time Protocol (NTP) right then. It’s like a wall clock and anyone could just go and change the time.
However, there’s a second type of clock which is just here to measure how time is passing. It usually knows only nanoseconds and just keeps counting them. Compare this to a stop watch.
Time drifts
The clock in your computer is corrected often (i.e. by NTP). Instead of just setting it to a new time it is set to run slower or faster until it’s synchronized. Manipulating the system clock drift prevents time jumps. So you can’t rely on it to measure time. Instead you need values from some high-resolution time source, such as System.nanoTime()
.
But don’t forget:
Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not correctly compute elapsed time due to numerical overflow.
JavaDoc for System.nanoTime
Don’t trust remote systems
Timestamps and other information from users could be made up and possibly manipulated to attack your system. Always use only one clock. For example the system clock on your server. With different system you can use the SQL database, if there is one:
SELECT CURRENT_TIMESTAMP; -- MSSQL
SELECT NOW(); -- MYSQL / postgresql
Again, don’t forget about time zones. You have to trust the client if you want to use local times.