diff options
author | Andrew White <andyw@pixeltrix.co.uk> | 2015-04-22 12:01:58 -0400 |
---|---|---|
committer | Andrew White <andyw@pixeltrix.co.uk> | 2015-04-22 12:05:07 -0400 |
commit | 5302d244eb2f81cba1bb0f1f6c8319464c467706 (patch) | |
tree | 8c5780b57636e2e6f6a3ac4de386a91354bb0cba | |
parent | a5e507fa0b8180c3d97458a9b86c195e9857d8f6 (diff) | |
download | rails-5302d244eb2f81cba1bb0f1f6c8319464c467706.tar.gz rails-5302d244eb2f81cba1bb0f1f6c8319464c467706.tar.bz2 rails-5302d244eb2f81cba1bb0f1f6c8319464c467706.zip |
Refactor ActiveSupport::Timezone#strptime
Make strptime behave more like parse when components are missing and
share behavior between the two methods.
-rw-r--r-- | activesupport/lib/active_support/values/time_zone.rb | 63 | ||||
-rw-r--r-- | activesupport/test/time_zone_test.rb | 9 |
2 files changed, 44 insertions, 28 deletions
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index ceeb9d3e08..2b59c7a33d 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -348,44 +348,31 @@ module ActiveSupport # # Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00 def parse(str, now=now()) - parts = Date._parse(str, false) - 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[:offset] - TimeWithZone.new(time.utc, self) - else - TimeWithZone.new(nil, self, time) - end + parts_to_time(Date._parse(str, false), now) end - # Parses +str+ according to +spec+ and returns an ActiveSupport::TimeWithZone. + # Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone. # # Assumes that +str+ is a time in the time zone +self+, - # unless +spec+ includes an explicit time zone. + # unless +format+ includes an explicit time zone. # (This is the same behavior as +parse+.) # In either case, the returned TimeWithZone has the timezone of +self+. # # Time.zone = 'Hawaii' # => "Hawaii" # Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S') # => Fri, 31 Dec 1999 14:00:00 HST -10:00 # - def strptime(str, spec) - case spec - when /(^|[^%](%%)*)%(Z|:{0,3}z)/ - DateTime.strptime(str, spec).in_time_zone(self) - else - t = DateTime.strptime(str, spec) - local(t.year, t.month, t.mday, t.hour, t.min, t.sec, t.usec) - end + # If upper components are missing from the string, they are supplied from + # TimeZone#now: + # + # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00 + # Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00 + # + # However, if the date component is not provided, but any other upper + # components are supplied, then the day of the month defaults to 1: + # + # Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00 + def strptime(str, format, now=now()) + parts_to_time(DateTime._strptime(str, format), now) end # Returns an ActiveSupport::TimeWithZone instance representing the current @@ -442,6 +429,26 @@ module ActiveSupport end private + def parts_to_time(parts, now) + 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[:offset] + TimeWithZone.new(time.utc, self) + else + TimeWithZone.new(nil, self, time) + end + end + def time_now Time.now end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 1293ccfd58..ea90caa143 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -376,6 +376,15 @@ class TimeZoneTest < ActiveSupport::TestCase assert_equal zone, twz.time_zone end + def test_strptime_with_day_omitted + with_env_tz 'US/Eastern' do + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + assert_equal Time.local(2000, 2, 1), zone.strptime('Feb', '%b', Time.local(2000, 1, 1)) + assert_equal Time.local(2005, 2, 1), zone.strptime('Feb 2005', '%b %Y', Time.local(2000, 1, 1)) + assert_equal Time.local(2005, 2, 2), zone.strptime('2 Feb 2005', '%e %b %Y', Time.local(2000, 1, 1)) + 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) |