From 07ffe7a6211b2bac59f385f4a0a67d11e4d42c24 Mon Sep 17 00:00:00 2001 From: denisovlev Date: Thu, 20 Oct 2016 15:44:22 +0300 Subject: [PATCH] Fix `ActiveSupport::TimeZone#strptime` cannot parse timestamps (%Q, %s) --- activesupport/CHANGELOG.md | 7 ++++++ .../lib/active_support/values/time_zone.rb | 24 +++++++++++-------- activesupport/test/time_zone_test.rb | 18 ++++++++++++++ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 91dfc556d3..13d152f4c6 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,10 @@ +* Fix `ActiveSupport::TimeZone#strptime`. + Support for timestamps in format of seconds (%s) and milliseconds (%Q). + + Fixes #26840. + + *Lev Denisov* + * Fix `DateAndTime::Calculations#copy_time_to`. Copy `nsec` instead of `usec`. Jumping forward or backward between weeks now preserves nanosecond digits. diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index cb97a0e135..a562f33420 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -450,17 +450,21 @@ module ActiveSupport raise ArgumentError, "invalid date" if parts.nil? return if parts.empty? - time = Time.new( - parts.fetch(:year, now.year), - parts.fetch(:mon, now.month), - parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day), - parts.fetch(:hour, 0), - parts.fetch(:min, 0), - parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0), - parts.fetch(:offset, 0) - ) + if parts[:seconds] + time = Time.at(parts[:seconds]) + else + time = Time.new( + parts.fetch(:year, now.year), + parts.fetch(:mon, now.month), + parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day), + parts.fetch(:hour, 0), + parts.fetch(:min, 0), + parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0), + parts.fetch(:offset, 0) + ) + end - if parts[:offset] + if parts[:offset] || parts[:seconds] TimeWithZone.new(time.utc, self) else TimeWithZone.new(nil, self, time) diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 76fee1fdd4..bd29584478 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -395,6 +395,24 @@ class TimeZoneTest < ActiveSupport::TestCase end end + def test_strptime_with_timestamp_seconds + with_env_tz "US/Eastern" do + zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"] + time_str = "1470272280" + time = zone.strptime(time_str, "%s") + assert_equal Time.at(1470272280), time + end + end + + def test_strptime_with_timestamp_milliseconds + with_env_tz "US/Eastern" do + zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"] + time_str = "1470272280000" + time = zone.strptime(time_str, "%Q") + assert_equal Time.at(1470272280), time + end + end + def test_utc_offset_lazy_loaded_from_tzinfo_when_not_passed_in_to_initialize tzinfo = TZInfo::Timezone.get("America/New_York") zone = ActiveSupport::TimeZone.create(tzinfo.name, nil, tzinfo)