2503ICT: Dates and times


Under construction!

Summary

Managing dates and times in computer programs is very complicated. First, there are the complexities of the solar system, leading to years, months, days, leap years and leap seconds. Then there are different calendars, different time zones, different daylight savings rules, and many different implementations.

An instant of time (such as 6:00pm on 15 May 2003) is called an epoch. Epochs are represented in Ruby as Unix timestamps (the integral number of seconds since 1 Jan 1970) and in SQLite as visual numerical strings. For example, the epoch at 21:30 on 15 May 2003 is represented by the Unix timestamp 1052998200 and by the SQLite timestamp "2003-05-15 21:30:00". Depending on the underlying operating system, timestamps may be recorded to the nearest millisecond, microsecond or nanosecond. So it's necessary to convert Unix timestamps to SQLite timestamps when inserting rows into SQLite tables and to convert SQLite timestamps to Unix timestamps when retrieving rows from SQLite tables. Fortunately, Rails does these conversions for us automatically.

An advantage of thinking in times of epochs or timestamps is that it's easy to add a number of seconds to an epoch to move forward in time and to subtract two epochs to find the difference between them.

In Ruby, there are three main classes for managing dates and times.

All three classes are in the library 'date', which is "required" whenever they are used.

Class DateTime is probably the most general and useful of the three classes. It has a larger range that class Time and it handles time zones better. It's possible to take the difference between two Date or DateTime instances and display the difference in terms of years, months and days. (Note that two intervals with the same number of seconds may represent different numbers of years, months and days, depending on when the intervals occur.)

Rails provides additional date helper functions, such as time_ago_in_words and distance_of_time_in_words. For example, the expression DateTime.now.to_date.advance(days: 5) returns the date in 5 days time. Alternatively:

from_time = Time.now
distance_of_time_in_words(from_time, from_time + 5.days + 1.hour)
==> 5 days

References