Comments (2)
I tried to follow the method chain for Time#<=>
, since it's used for >=
comparisons. In Rails, that method is defined as #compare_with_coercion
:
rails/activesupport/lib/active_support/core_ext/time/calculations.rb
Lines 315 to 328 in c7551d0
The integer value on the right side of the comparison isn't Time
-ish, so the Time
object on the left side gets converted to a DateTime
and then compared to the integer value. DateTime#<=>
checks if the object on the right side responds to #to_datetime
and goes up the inheritance chain if not (which is the case here):
rails/activesupport/lib/active_support/core_ext/date_time/calculations.rb
Lines 206 to 214 in c7551d0
The super-method in this case is Date#<=>
. There's a method in Rails for this, but it ends up calling the native #<=>
method for DateTime
(which is defined on Date
) if the object on the right side isn't a Time
:
rails/activesupport/lib/active_support/core_ext/date/calculations.rb
Lines 151 to 160 in c7551d0
Here's the twist. While I didn't read through the C code for the native Date#<=>
, https://ruby-doc.org/3.2.2/exts/date/Date.html#method-i-3C-3D-3E specifically notes that when comparing to a numeric value, the #ajd
method is called on the Date
and the resulting value is compared to the numeric value on the right side. That #ajd
method is the "astronomical Julian day number"; I wouldn't have been able to tell you what that meant before today, but the important thing is that it's a count of days (since about 6700 years ago) and nowadays is between 2_000_000 and 3_000_000. But the integer on the right side of the comparison came from calling Time#to_i
, and that's the number of seconds since January 1, 1970, currently a bit over 1_700_000_000. So you have to subtract a very large number from Time.now.to_i
in order for Time.now
to compare as greater. And for what it's worth, this also affects DateTime
comparisons to integers.
I haven't checked to see how far back this behavior goes.
from rails.
To follow up on this a bit and lend support to the original statement of the issue, I think it makes sense that for any Time
instances t1
and t2
, if t1 > t2
evaluates to true and t1.to_i > t2.to_i
evaluates to true, then t1 > t2.to_i
should either evaluate to true or raise an exception. Instead, due to unexpected coercion, t1 > t2.to_i
is only true if t2
is on or before 1970-01-29 (the latest day that included a time when the number of seconds since the Unix epoch was less than the astronomical Julian day number) or t1
is very far in the future. All of this goes for DateTime
instances as well.
In terms of solving this, I'm not sure whether it makes more sense to fix it in Time
or DateTime
. Fixing it in DateTime
should also address the issue in Time
(due to the partial delegation of Time#<=>
to DateTime#<=>
) but it isn't clear to me what the solution would be for DateTime
. I'm assuming that there isn't much interest in making DateTime#<=>
coerce the object into Unix time when comparing to a numeric value, since that could cause the method to return a completely different value just by adding Active Support to a project. Alternatively, the DateTime#to_i
method in Active Support could be changed to return the astronomical Julian day number instead of Unix time, which would be more conceptually consistent with Ruby. But that method has returned the Unix time in Rails for almost 15 years, and DateTime#to_f
has returned a comparable number for even longer. And since Ruby considers DateTime
deprecated, maybe it makes sense to just fix the issue in Time
and not worry about DateTime
?
from rails.
Related Issues (20)
- counter_cache doesn't work with composite PKs HOT 1
- Active Record marks attributes as `came_from_user?` after `dup`
- Active Record marks attributes as `_changed?` after `dup`ing a persisted instance HOT 1
- ActiveSupport::TimeZone.new raises ArgumentError HOT 6
- [Rails 7.1.3] async_find_by_sql needs promise.value.value ?! HOT 1
- allow_browser may prevent your site from being crawled HOT 2
- Add the ability to configure minimum number of active connections for connection pool
- jemalloc Dockerfile configuration may be problematic across architectures HOT 1
- Trilogy:EOFError cannot be recovered on ActiveRecord 7.1 HOT 1
- Rails error reporter doesn't report exceptions in production HOT 5
- Sidekiq ActiveJob adapter resets provider_job_id on with retry_job HOT 3
- Passing an array to the `model` parameter of `form_with` does not work with singular, unpersisted resources HOT 1
- Read the Ruby Version in Gemfile Instead of Hardcoding the Version HOT 2
- `render "fizz"` and `render partial: "fizz"` behave differently when given a block HOT 2
- Pure ruby view templates, pages and components HOT 1
- `FileNotFoundError` in `AnalyzeJob` HOT 1
- nested_attributes_for :limit does not account for records marked for deletion
- no implicit conversion of String into Integer (TypeError) @env[name] HOT 2
- Relation `#distinct` doesn't raise an error for invalid arguments HOT 2
- ActiveModel::Dirty is broken in after_commit
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rails.