-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: 7.0.6, 7.1.0
-
Component/s: Query
Given the following model:
class Person include Mongoid::Document field :dob, type: Date end
A user can query the dob field of this model using a Time value.
Time.now # => 2020-04-22 15:27:39 -0400 Person.lte(dob: Time.now) # => selector: {"dob"=>{"$lte"=>2020-04-22 00:00:00 UTC}}
During that query, the original Time is converted to a different Time instance equivalent to midnight UTC on the same day as the original Time.
However, when the same field is queried using a TimeWithZone value, the query is constructed using a TimeWithZone value equivalent to midnight on that same day in the current time zone.
Time.use_zone('Europe/Moscow') { Person.lte(dob: Time.zone.now) } # {"dob"=>{"$lte"=>Wed, 22 Apr 2020 00:00:00 MSK +03:00}}
The behavior between these two classes is inconsistent. I believe that when TimeWithZone values are used to query Date fields, a TimeWithZone equivalent to midnight on that day in UTC should be used as the query value.
The original ticket description is below:
The following spec used to pass up to and including Mongoid 7.0.5 and started failing with Mongoid 7.0.6:
require "spec_helper" describe "Date valued fields" do context "when the TimeZone is ahead of UTC" do around do |example| Time.use_zone('Europe/Moscow') do example.run end end let!(:match) do Person.create(dob: Time.zone.today) end let!(:non_match) do Person.create(dob: Time.zone.tomorrow) end it "returns the matching documents" do expect(Person.lte(dob: Time.zone.now)).to match_array([match]) end end context "when the TimeZone is trailing UTC" do around do |example| Time.use_zone('America/New_York') do example.run end end let!(:match) do Person.create(dob: Time.zone.today) end let!(:non_match) do Person.create(dob: Time.zone.yesterday) end it "returns the matching documents" do expect(Person.gte(dob: Time.zone.now.beginning_of_day)).to match_array([match]) end end end
The reason is the introduction of mongo/active_support:
In the first case we try to match 2020-03-12 with Mongoid's selector
{ "dob" => {"$lte"=>Thu, 12 Mar 2020 00:00:00 MSK +03:00} }
which is equivalent to
{ "dob" => {"$lte"=>Wed, 11 Mar 2020 21:00:00 UTC} }
The match will succeed if we expand 2020-03-12 into Thu, 12 Mar 2020 00:00:00 MSK +03:00 and fail if we interpret it as Thu, 12 Mar 2020 00:00:00 UTC.
- is related to
-
RUBY-2179 Document that dates are serialized as midnight in UTC
- Closed
- links to