Skip to content

Instantly share code, notes, and snippets.

@pixeltrix
Last active August 2, 2024 15:13
Show Gist options
  • Save pixeltrix/e2298822dd89d854444b to your computer and use it in GitHub Desktop.
Save pixeltrix/e2298822dd89d854444b to your computer and use it in GitHub Desktop.
When should you use DateTime and when should you use Time?

When should you use DateTime and when should you use Time?

It's a common misconception that William Shakespeare and Miguel de Cervantes died on the same day in history - so much so that UNESCO named April 23 as World Book Day because of this fact. However because England hadn't yet adopted Gregorian Calendar Reform (and wouldn't until 1752) their deaths are actually 10 days apart. Since Ruby's Time class implements a proleptic Gregorian calendar and has no concept of calendar reform then there's no way to express this. This is where DateTime steps in:

>> shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND)
=> Tue, 23 Apr 1616 00:00:00 +0000
>> cervantes = DateTime.iso8601('1616-04-23', Date::ITALY)
=> Sat, 23 Apr 1616 00:00:00 +0000

Already you can see something's weird - the days of the week are different, taking this further:

>> cervantes == shakespeare
=> false
>> (shakespeare - cervantes).to_i
=> 10

This shows that in fact they died 10 days apart (in reality 11 days since Cervantes died a day earlier but was buried on the 23rd). We can see the actual date of Shakespeare's death by using the gregorian method to convert it:

>> shakespeare.gregorian
=> Tue, 03 May 1616 00:00:00 +0000

So there's an argument that all the celebrations that take place on the 23rd April in Stratford-upon-Avon are actually the wrong date since England is now using the Gregorian calendar. You can see why when we transition across the reform date boundary:

# start off with the anniversary of Shakespeare's birth in 1751
>> shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND)
=> Tue, 23 Apr 1751 00:00:00 +0000

# add 366 days since 1752 is a leap year and April 23 is after February 29
>> shakespeare + 366
=> Thu, 23 Apr 1752 00:00:00 +0000

# add another 365 days to take us to the anniversary in 1753
>> shakespeare + 366 + 365
=> Fri, 04 May 1753 00:00:00 +0000

As you can see, if we're accurately tracking the number of solar years since Shakespeare's birthday then the correct anniversary date would be the 4th May and not the 23rd April.

So when should use you use DateTime in Ruby and when should you use Time? Almost certainly you'll want to use Time since your app is probably dealing with current dates and times and it has support for timezones (system/local and utc), whereas DateTime just has offsets from UTC. However, if you need to deal with dates and times in a historical context you'll want to use DateTime to avoid making the same mistakes as UNESCO. If you also have to deal with timezones then best of luck - just bear in mind that you'll probably be dealing with local solar times, since it wasn't until the 19th century that the introduction of the railways necessitated the need for Standard Time and eventually timezones.

@akostadinov
Copy link

@callenb, I think issue is how you assign time. Otherwise time formatting should take care of what you need. e.g. if you print the UTC offset, it will be apparent whether time is before or after switchover.

@callenb
Copy link

callenb commented Oct 30, 2021

@akostadinov I convert all incoming dates into UTC, perform calculations and then convert back out to the Time Zone they were supplied in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment