Tallboy
Tallboy

Reputation: 13417

Rails TimeWithZone doesn't match

I've been having a terrible time with 2 times that are saying it's not equal

# returns TRUE before persisted, but when retrieved from postgres it's FALSE
end_date == end_date.in_time_zone('Eastern Time (US & Canada)').end_of_day

Your immediate thought is probably usec however I have checked that many times already, and both are 999999:

[21] pry(#<Lease>)> end_date.usec
=> 999999
[22] pry(#<Lease>)> end_date.in_time_zone('Eastern Time (US & Canada)').end_of_day.usec
=> 999999
[23] pry(#<Lease>)> end_date.to_i
=> 1580533199
[24] pry(#<Lease>)> end_date.in_time_zone('Eastern Time (US & Canada)').end_of_day.to_i
=> 1580533199
[25] pry(#<Lease>)> end_date.class
=> ActiveSupport::TimeWithZone
[26] pry(#<Lease>)> end_date.in_time_zone('Eastern Time (US & Canada)').end_of_day.class
=> ActiveSupport::TimeWithZone
[33] pry(#<Lease>)> end_date.iso8601
=> "2020-02-01T04:59:59Z"
[34] pry(#<Lease>)> end_date.in_time_zone('Eastern Time (US & Canada)').end_of_day.utc.iso8601
=> "2020-02-01T04:59:59Z"

This is driving me insane, I don't know what else to check...

Edit: it appears nsec is what is different. How the heck am I supposed to account for this? How do I truncate nanoseconds to a certain precision (6). Unless there's a better way to handle this when my times involve the 'end of the month' (the end of some term)

Upvotes: 1

Views: 387

Answers (1)

mrzasa
mrzasa

Reputation: 23327

When a model is saved to the DB those timestamps are stored in a type timestamp without time zone that has microsecond resolution. When you have nanosecond precision in your time, it'll be truncated.

To fix it, you could try to:

  • approximate a date with round to full microseconds:
1.day.ago.round(6).nsec
#=> 158812000
1.day.ago.round(6)
#=> Wed, 28 Aug 2019 03:21:51 EDT -04:00

  • store the beginning of the next day

I'm aware that those are not the perfect solutions, can't think about a better one now.

Upvotes: 1

Related Questions