Skip to content

Commit eed59fa

Browse files
committed
DateTime mild roast
1 parent 2595413 commit eed59fa

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
created_at: 2026-01-14 15:08:58 +0100
3+
author: Szymon Fiedler
4+
tags: [ruby, rails, time, datetime, legacy]
5+
publish: false
6+
---
7+
8+
# Stop using DateTime in 2026 (unless you work for UNESCO)
9+
10+
`DateTime` has been deprecated in Ruby since 3.0. It's 2026. Why are people still using it?
11+
12+
<!-- more -->
13+
14+
During a recent code review, we found this:
15+
16+
```ruby
17+
whatever.starts_at = DateTime.now
18+
```
19+
20+
When asked why `DateTime` instead of `Time`, the response was: "`DateTime` handles a wider range of dates."
21+
22+
That was partially true. In 2008. On 32-bit systems.
23+
24+
## DateTime's range advantage died in Ruby 1.9.2
25+
26+
Before Ruby 1.9.2 (released in 2010), Time was limited by the system's `time_t` type — typically 32-bit signed integer covering 1901-2038. `DateTime` had a much wider range.
27+
28+
[Ruby 1.9.2 changed this](https://ruby-doc.org/core-2.1.9/Time.html). Time started using a signed 63-bit integer representing nanoseconds since epoch, giving it a range of 1823-2116. For dates outside this range, `Time` uses `Bignum` or `Rational` — slower, but it works.
29+
30+
The practical range advantage is gone.
31+
32+
## Remember Rails 4.2?
33+
34+
[_Pepperidge Farm Remembers_](https://knowyourmeme.com/memes/pepperidge-farm-remembers).
35+
Some time ago when upgrading Rails app from 4.2 to 5.0, the test suite fortunately failed. The culprit was surprising: `DateTime#utc` changed its return type.
36+
37+
[Rails 4.2](https://api.rubyonrails.org/v4.2/classes/DateTime.html#method-i-utc):
38+
39+
```ruby
40+
DateTime.now.utc.class
41+
# => DateTime
42+
```
43+
44+
[Rails 5.0](https://api.rubyonrails.org/v5.0/classes/DateTime.html#method-i-utc):
45+
46+
```ruby
47+
DateTime.now.utc.class # => Time
48+
```
49+
50+
This broke several `Dry::Struct` objects with strict type definitions expecting `DateTime`. But instead of "fixing" the types, we asked a better question: *why were we using `DateTime` at all?*
51+
52+
Rails 5's breaking change to `DateTime#utc` wasn't a bug — it was a nudge. It was telling you: stop using this class.
53+
54+
[Struggling with upgrades? We have a solution for you](https://arkency.com/ruby-on-rails-upgrades/).
55+
56+
## The UNESCO problem
57+
58+
There's actually **one** legitimate use case for `DateTime`: historical calendar reforms.
59+
60+
From [Ruby's own documentation](https://ruby-doc.org/stdlib-2.4.1/libdoc/date/rdoc/DateTime.html):
61+
62+
> 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 the Gregorian Calendar Reform (and wouldn't until 1752) their deaths are actually 10 days apart.
63+
64+
Ruby's `Time` uses a proleptic Gregorian calendar — it projects the Gregorian calendar backwards, ignoring historical reality. October 10, 1582 doesn't exist in Italy (Pope Gregory XIII removed 10 days that October), but Ruby happily creates that timestamp.
65+
66+
`DateTime` can handle different calendar reform dates:
67+
68+
```ruby
69+
shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND)
70+
cervantes = DateTime.iso8601('1616-04-23', Date::ITALY)
71+
72+
(shakespeare - cervantes).to_i # => 10 days apart
73+
```
74+
75+
For cataloging historical artifacts or dealing with pre-1752 dates across different countries, `DateTime` is your tool.
76+
77+
For literally everything else — which is 99.99% of applications — it's the wrong choice.
78+
79+
Norbert Wójtowicz gave an excellent [talk about calendars at wroclove.rb](https://www.youtube.com/watch?v=YiLlnsq2fJ4) covering exactly these issues.
80+
81+
## `DateTime`’s actual problems
82+
83+
**No timezone support**. DateTime doesn't handle timezones.
84+
85+
```ruby
86+
DateTime.now
87+
# => #<DateTime: 2026-01-14T13:00:00+00:00>
88+
# Why +00:00 when my system is CET (+01:00)?
89+
```
90+
91+
**Incompatible with Rails**. `ActiveSupport` extends `Time` with timezone support. `DateTime`? Barely.
92+
93+
```ruby
94+
Time.current # ✅ Respects Rails.application.config.time_zone
95+
DateTime.now # ❌ Uses system timezone, ignores Rails config
96+
```
97+
98+
**Confusing arithmetic**:
99+
100+
```ruby
101+
Time.now + 1 # => 1 second later
102+
DateTime.now + 1 # => 1 day later
103+
```
104+
105+
This has caused bugs. Many bugs.
106+
107+
**Ignores DST**. `DateTime` doesn't track daylight saving time. We covered this in [our previous post about timezone bugs](#), but the summary: if you use DateTime for anything involving timezones, you will have bugs.
108+
109+
**Performance**. `Time` is faster. Noticeably.
110+
111+
## Why people still use it
112+
113+
**"We've always used it"**
114+
115+
The code was written in 2009. It's 2026. Update it.
116+
117+
**"I need to store dates without time"**
118+
119+
Use `Date`. That's what it's for.
120+
121+
```ruby
122+
Date.current # ✅ Rails.application.config.time_zone aware
123+
```
124+
125+
**"The library I'm using returns DateTime"**
126+
127+
Convert immediately:
128+
129+
```ruby
130+
legacy_gem.fetch_date.to_time.in_time_zone
131+
```
132+
133+
## What to use instead
134+
135+
For timestamps: `Time.current` or `Time.zone.now`
136+
For dates: `Date.current`
137+
For parsing: `Time.zone.parse('2026-01-14 13:00:00')`
138+
139+
## The only exception
140+
141+
If you're cataloging historical documents, artifacts, or working with dates before calendar reforms in different countries, `DateTime` is your tool. You need to track which calendar reform date applies.
142+
143+
For everything else — modern applications, APIs, databases — use `Time`.
144+
145+
`DateTime` is deprecated for a reason.
146+
147+
## References
148+
149+
- [Ruby Time documentation - Ruby 1.9.2 changes](https://ruby-doc.org/core-2.1.9/Time.html)
150+
- [Ruby DateTime documentation - UNESCO calendar problem](https://ruby-doc.org/stdlib-2.4.1/libdoc/date/rdoc/DateTime.html)
151+
- [Norbert Wójtowicz - It's About Time (wroclove.rb)](https://www.youtube.com/watch?v=YiLlnsq2fJ4)
152+
- [Ruby Style Guide: No DateTime](https://rubystyle.guide/#no-datetime)

0 commit comments

Comments
 (0)