New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
quoted_date has an hour window of failure for timestamp with timezone #38189
Comments
This issue has been automatically marked as stale because it has not been commented on for at least three months. |
If I am understanding correctly, this is actually a problem for all databases when Some Ruby to illustrate the pointENV["TZ"] = "America/New_York"
zone = ActiveSupport::TimeZone[ENV["TZ"]]
twzs = [
zone.parse("2018-11-04 00:59:00 -04:00"), # == Sun, 04 Nov 2018 00:59:00 EDT -04:00
zone.parse("2018-11-04 01:30:00 -04:00"), # == Sun, 04 Nov 2018 01:30:00 EDT -04:00
zone.parse("2018-11-04 01:30:00 -05:00"), # == Sun, 04 Nov 2018 01:30:00 EST -05:00
zone.parse("2018-11-04 02:01:00 -05:00"), # == Sun, 04 Nov 2018 02:01:00 EST -05:00
]
quoted_utc = twzs.map{|twz| twz.getutc.to_s(:db) }
# == [
# "2018-11-04 04:59:00",
# "2018-11-04 05:30:00",
# "2018-11-04 06:30:00",
# "2018-11-04 07:01:00",
# ]
quoted_local = twzs.map{|twz| twz.getlocal.to_s(:db) }
# == [
# "2018-11-04 00:59:00",
# "2018-11-04 01:30:00",
# "2018-11-04 01:30:00",
# "2018-11-04 02:01:00",
# ] If we appended time zone offsets to quoted times, zone-aware data types (like PostgreSQL's Some SQL to illustrate the pointCREATE TABLE facepalm (s VARCHAR, t TIMESTAMP, ttz_utc TIMESTAMPTZ, ttz_east TIMESTAMPTZ);
INSERT INTO facepalm (s) VALUES
('2018-11-04 04:59:00'),
('2018-11-04 05:30:00'),
('2018-11-04 06:30:00'),
('2018-11-04 07:01:00'),
('2018-11-04 04:59:00z'),
('2018-11-04 05:30:00z'),
('2018-11-04 06:30:00z'),
('2018-11-04 07:01:00z'),
('2018-11-04 00:59:00'),
('2018-11-04 01:30:00'),
('2018-11-04 01:30:00'),
('2018-11-04 02:01:00'),
('2018-11-04 00:59:00 -04:00'),
('2018-11-04 01:30:00 -04:00'),
('2018-11-04 01:30:00 -05:00'),
('2018-11-04 02:01:00 -05:00');
UPDATE facepalm SET t = s::TIMESTAMP;
SET TIME ZONE "Etc/UTC";
UPDATE facepalm SET ttz_utc = s::TIMESTAMPTZ;
SET TIME ZONE "America/New_York";
UPDATE facepalm SET ttz_east = s::TIMESTAMPTZ;
SELECT * FROM facepalm;
On the plus side, PostgreSQL will happily ignore a time zone offset if the column type is plain |
When I try this, the # SET TIME ZONE "Etc/UTC";
# SELECT * FROM facepalm;
s | t | ttz_utc | ttz_east
----------------------------+---------------------+------------------------+------------------------
2018-11-04 04:59:00 | 2018-11-04 04:59:00 | 2018-11-04 04:59:00+00 | 2018-11-04 09:59:00+00
2018-11-04 05:30:00 | 2018-11-04 05:30:00 | 2018-11-04 05:30:00+00 | 2018-11-04 10:30:00+00
2018-11-04 06:30:00 | 2018-11-04 06:30:00 | 2018-11-04 06:30:00+00 | 2018-11-04 11:30:00+00
2018-11-04 07:01:00 | 2018-11-04 07:01:00 | 2018-11-04 07:01:00+00 | 2018-11-04 12:01:00+00
2018-11-04 04:59:00z | 2018-11-04 04:59:00 | 2018-11-04 04:59:00+00 | 2018-11-04 04:59:00+00
2018-11-04 05:30:00z | 2018-11-04 05:30:00 | 2018-11-04 05:30:00+00 | 2018-11-04 05:30:00+00
2018-11-04 06:30:00z | 2018-11-04 06:30:00 | 2018-11-04 06:30:00+00 | 2018-11-04 06:30:00+00
2018-11-04 07:01:00z | 2018-11-04 07:01:00 | 2018-11-04 07:01:00+00 | 2018-11-04 07:01:00+00
2018-11-04 00:59:00 | 2018-11-04 00:59:00 | 2018-11-04 00:59:00+00 | 2018-11-04 04:59:00+00
2018-11-04 01:30:00 | 2018-11-04 01:30:00 | 2018-11-04 01:30:00+00 | 2018-11-04 06:30:00+00
2018-11-04 01:30:00 | 2018-11-04 01:30:00 | 2018-11-04 01:30:00+00 | 2018-11-04 06:30:00+00
2018-11-04 02:01:00 | 2018-11-04 02:01:00 | 2018-11-04 02:01:00+00 | 2018-11-04 07:01:00+00
2018-11-04 00:59:00 -04:00 | 2018-11-04 00:59:00 | 2018-11-04 04:59:00+00 | 2018-11-04 04:59:00+00
2018-11-04 01:30:00 -04:00 | 2018-11-04 01:30:00 | 2018-11-04 05:30:00+00 | 2018-11-04 05:30:00+00
2018-11-04 01:30:00 -05:00 | 2018-11-04 01:30:00 | 2018-11-04 06:30:00+00 | 2018-11-04 06:30:00+00
2018-11-04 02:01:00 -05:00 | 2018-11-04 02:01:00 | 2018-11-04 07:01:00+00 | 2018-11-04 07:01:00+00
(16 rows)
# SET TIME ZONE "America/New_York";
# SELECT * FROM facepalm;
s | t | ttz_utc | ttz_east
----------------------------+---------------------+------------------------+------------------------
2018-11-04 04:59:00 | 2018-11-04 04:59:00 | 2018-11-04 00:59:00-04 | 2018-11-04 04:59:00-05
2018-11-04 05:30:00 | 2018-11-04 05:30:00 | 2018-11-04 01:30:00-04 | 2018-11-04 05:30:00-05
2018-11-04 06:30:00 | 2018-11-04 06:30:00 | 2018-11-04 01:30:00-05 | 2018-11-04 06:30:00-05
2018-11-04 07:01:00 | 2018-11-04 07:01:00 | 2018-11-04 02:01:00-05 | 2018-11-04 07:01:00-05
2018-11-04 04:59:00z | 2018-11-04 04:59:00 | 2018-11-04 00:59:00-04 | 2018-11-04 00:59:00-04
2018-11-04 05:30:00z | 2018-11-04 05:30:00 | 2018-11-04 01:30:00-04 | 2018-11-04 01:30:00-04
2018-11-04 06:30:00z | 2018-11-04 06:30:00 | 2018-11-04 01:30:00-05 | 2018-11-04 01:30:00-05
2018-11-04 07:01:00z | 2018-11-04 07:01:00 | 2018-11-04 02:01:00-05 | 2018-11-04 02:01:00-05
2018-11-04 00:59:00 | 2018-11-04 00:59:00 | 2018-11-03 20:59:00-04 | 2018-11-04 00:59:00-04
2018-11-04 01:30:00 | 2018-11-04 01:30:00 | 2018-11-03 21:30:00-04 | 2018-11-04 01:30:00-05
2018-11-04 01:30:00 | 2018-11-04 01:30:00 | 2018-11-03 21:30:00-04 | 2018-11-04 01:30:00-05
2018-11-04 02:01:00 | 2018-11-04 02:01:00 | 2018-11-03 22:01:00-04 | 2018-11-04 02:01:00-05
2018-11-04 00:59:00 -04:00 | 2018-11-04 00:59:00 | 2018-11-04 00:59:00-04 | 2018-11-04 00:59:00-04
2018-11-04 01:30:00 -04:00 | 2018-11-04 01:30:00 | 2018-11-04 01:30:00-04 | 2018-11-04 01:30:00-04
2018-11-04 01:30:00 -05:00 | 2018-11-04 01:30:00 | 2018-11-04 01:30:00-05 | 2018-11-04 01:30:00-05
2018-11-04 02:01:00 -05:00 | 2018-11-04 02:01:00 | 2018-11-04 02:01:00-05 | 2018-11-04 02:01:00-05
(16 rows)
I'm at 9.6 though, maybe that is the difference? |
I think that was a rendering artifact of using SQL Fiddle and its default PostgreSQL / JDBC settings. I don't think it affects the underlying issue. For what it's worth, SQL Fiddle uses 9.6 also. |
@rafaelfranca Would you mind re-opening this issue and adding the "with reproduction steps" tag? |
Description
This is a catch-22. The code is built to work well with timestamp without time zone (and that is the convention for things like created_at/updated_at). However, for timestamp with time zone and timezones with DST there exists a window of time where this causes any timestamp within that window to disappear, shifting the offset to standard time.
Steps to reproduce
For details, see actual behavior.
Expected behavior
The timestamp with timezone should be persisted with the correct timezone.
Actual behavior
Example (while in Eastern Standard Time):
model.update(time_column: Time.new(2018,11,04,01,01,00,'-04:00'))
System configuration
Rails version:
2.5
Ruby version:
2.4
Attempted workarounds
Add timezone to all db activities:
config/initializers/time_formats.rb
Broken by https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb#L115
This appends the microseconds to the string after the offset format.
Final solution?
I will probably have to monkey patch which I hate. I don't see a good global resolution offhand unless there's a new approach for timestamp with timezone that is separate from timestamp without time zone?
Looking for other suggestions.
The text was updated successfully, but these errors were encountered: