Skip to content

Commit

Permalink
Add ActiveSupport::TimeZone#strptime.
Browse files Browse the repository at this point in the history
This makes it easier to parse user-inputted times as from a given time zone.
  • Loading branch information
pjungwir authored and pixeltrix committed Apr 22, 2015
1 parent 9a034bc commit a5e507f
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
5 changes: 5 additions & 0 deletions activesupport/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
* Added `ActiveSupport::TimeZone#strptime` to allow parsing times as if
from a given timezone.

*Paul A Jungwirth*

* `ActiveSupport::Callbacks#skip_callback` now raises an `ArgumentError` if
an unrecognized callback is removed.

Expand Down
20 changes: 20 additions & 0 deletions activesupport/lib/active_support/values/time_zone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,26 @@ def parse(str, now=now())
end
end

# Parses +str+ according to +spec+ and returns an ActiveSupport::TimeWithZone.
#
# Assumes that +str+ is a time in the time zone +self+,
# unless +spec+ 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
end

# Returns an ActiveSupport::TimeWithZone instance representing the current
# time in the time zone represented by +self+.
#
Expand Down
65 changes: 65 additions & 0 deletions activesupport/test/time_zone_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,71 @@ def test_parse_handles_dst_jump
end
end

def test_strptime
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.strptime('1999-12-31 12:00:00', '%Y-%m-%d %H:%M:%S')
assert_equal Time.utc(1999,12,31,17), twz
assert_equal Time.utc(1999,12,31,12), twz.time
assert_equal Time.utc(1999,12,31,17), twz.utc
assert_equal zone, twz.time_zone
end

def test_strptime_with_nondefault_time_zone
with_tz_default ActiveSupport::TimeZone['Pacific Time (US & Canada)'] do
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.strptime('1999-12-31 12:00:00', '%Y-%m-%d %H:%M:%S')
assert_equal Time.utc(1999,12,31,17), twz
assert_equal Time.utc(1999,12,31,12), twz.time
assert_equal Time.utc(1999,12,31,17), twz.utc
assert_equal zone, twz.time_zone
end
end

def test_strptime_with_explicit_time_zone_as_abbrev
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.strptime('1999-12-31 12:00:00 PST', '%Y-%m-%d %H:%M:%S %Z')
assert_equal Time.utc(1999,12,31,20), twz
assert_equal Time.utc(1999,12,31,15), twz.time
assert_equal Time.utc(1999,12,31,20), twz.utc
assert_equal zone, twz.time_zone
end

def test_strptime_with_explicit_time_zone_as_h_offset
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.strptime('1999-12-31 12:00:00 -08', '%Y-%m-%d %H:%M:%S %:::z')
assert_equal Time.utc(1999,12,31,20), twz
assert_equal Time.utc(1999,12,31,15), twz.time
assert_equal Time.utc(1999,12,31,20), twz.utc
assert_equal zone, twz.time_zone
end

def test_strptime_with_explicit_time_zone_as_hm_offset
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.strptime('1999-12-31 12:00:00 -08:00', '%Y-%m-%d %H:%M:%S %:z')
assert_equal Time.utc(1999,12,31,20), twz
assert_equal Time.utc(1999,12,31,15), twz.time
assert_equal Time.utc(1999,12,31,20), twz.utc
assert_equal zone, twz.time_zone
end

def test_strptime_with_explicit_time_zone_as_hms_offset
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.strptime('1999-12-31 12:00:00 -08:00:00', '%Y-%m-%d %H:%M:%S %::z')
assert_equal Time.utc(1999,12,31,20), twz
assert_equal Time.utc(1999,12,31,15), twz.time
assert_equal Time.utc(1999,12,31,20), twz.utc
assert_equal zone, twz.time_zone
end

def test_strptime_with_almost_explicit_time_zone
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
twz = zone.strptime('1999-12-31 12:00:00 %Z', '%Y-%m-%d %H:%M:%S %%Z')
assert_equal Time.utc(1999,12,31,17), twz
assert_equal Time.utc(1999,12,31,12), twz.time
assert_equal Time.utc(1999,12,31,17), twz.utc
assert_equal zone, twz.time_zone
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)
Expand Down

0 comments on commit a5e507f

Please sign in to comment.