mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add ActiveSupport::TimeZone.rfc3339
parsing method
Previously there was no way to get a RFC 3339 timestamp into a specific timezone without either using `parse` or chaining methods. The new method allows parsing directly into the timezone, e.g: >> Time.zone = "Hawaii" => "Hawaii" >> Time.zone.rfc3339("1999-12-31T14:00:00Z") => Fri, 31 Dec 1999 14:00:00 HST -10:00 This new method has stricter semantics than the current `parse` method and will raise an `ArgumentError` instead of returning nil, e.g: >> Time.zone = "Hawaii" => "Hawaii" >> Time.zone.rfc3339("foobar") ArgumentError: invalid date >> Time.zone.parse("foobar") => nil It will also raise an `ArgumentError` when either the time or offset components are missing, e.g: >> Time.zone = "Hawaii" => "Hawaii" >> Time.zone.rfc3339("1999-12-31") ArgumentError: invalid date >> Time.zone.rfc3339("1999-12-31T14:00:00") ArgumentError: invalid date
This commit is contained in:
parent
4974b1a483
commit
f61062c70f
3 changed files with 173 additions and 0 deletions
|
@ -1,3 +1,36 @@
|
|||
* Add `ActiveSupport::TimeZone.rfc3339` parsing method
|
||||
|
||||
Previously there was no way to get a RFC 3339 timestamp into a specific
|
||||
timezone without either using `parse` or chaining methods. The new method
|
||||
allows parsing directly into the timezone, e.g:
|
||||
|
||||
>> Time.zone = "Hawaii"
|
||||
=> "Hawaii"
|
||||
>> Time.zone.rfc3339("1999-12-31T14:00:00Z")
|
||||
=> Fri, 31 Dec 1999 14:00:00 HST -10:00
|
||||
|
||||
This new method has stricter semantics than the current `parse` method
|
||||
and will raise an `ArgumentError` instead of returning nil, e.g:
|
||||
|
||||
>> Time.zone = "Hawaii"
|
||||
=> "Hawaii"
|
||||
>> Time.zone.rfc3339("foobar")
|
||||
ArgumentError: invalid date
|
||||
>> Time.zone.parse("foobar")
|
||||
=> nil
|
||||
|
||||
It will also raise an `ArgumentError` when either the time or offset
|
||||
components are missing, e.g:
|
||||
|
||||
>> Time.zone = "Hawaii"
|
||||
=> "Hawaii"
|
||||
>> Time.zone.rfc3339("1999-12-31")
|
||||
ArgumentError: invalid date
|
||||
>> Time.zone.rfc3339("1999-12-31T14:00:00")
|
||||
ArgumentError: invalid date
|
||||
|
||||
*Andrew White*
|
||||
|
||||
* Add `ActiveSupport::TimeZone.iso8601` parsing method
|
||||
|
||||
Previously there was no way to get a ISO 8601 timestamp into a specific
|
||||
|
|
|
@ -394,6 +394,36 @@ module ActiveSupport
|
|||
parts_to_time(Date._parse(str, false), now)
|
||||
end
|
||||
|
||||
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
||||
# of +self+ from an RFC 3339 string.
|
||||
#
|
||||
# Time.zone = 'Hawaii' # => "Hawaii"
|
||||
# Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
||||
#
|
||||
# If the time or zone components are missing then an +ArgumentError+ will
|
||||
# be raised. This is much stricter than either +parse+ or +iso8601+ which
|
||||
# allow for missing components.
|
||||
#
|
||||
# Time.zone = 'Hawaii' # => "Hawaii"
|
||||
# Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
|
||||
def rfc3339(str)
|
||||
parts = Date._rfc3339(str)
|
||||
|
||||
raise ArgumentError, "invalid date" if parts.empty?
|
||||
|
||||
time = Time.new(
|
||||
parts.fetch(:year),
|
||||
parts.fetch(:mon),
|
||||
parts.fetch(:mday),
|
||||
parts.fetch(:hour),
|
||||
parts.fetch(:min),
|
||||
parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
|
||||
parts.fetch(:offset)
|
||||
)
|
||||
|
||||
TimeWithZone.new(time.utc, self)
|
||||
end
|
||||
|
||||
# Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
|
||||
#
|
||||
# Assumes that +str+ is a time in the time zone +self+,
|
||||
|
|
|
@ -223,6 +223,23 @@ class TimeZoneTest < ActiveSupport::TestCase
|
|||
assert_equal zone, twz.time_zone
|
||||
end
|
||||
|
||||
def test_iso8601_with_fractional_seconds
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
twz = zone.iso8601("1999-12-31T19:00:00.750")
|
||||
assert_equal 750000, twz.time.usec
|
||||
assert_equal Time.utc(1999, 12, 31, 19, 0, 0 + Rational(3, 4)), twz.time
|
||||
assert_equal Time.utc(2000, 1, 1, 0, 0, 0 + Rational(3, 4)), twz.utc
|
||||
assert_equal zone, twz.time_zone
|
||||
end
|
||||
|
||||
def test_iso8601_with_zone
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
twz = zone.iso8601("1999-12-31T14:00:00-10:00")
|
||||
assert_equal Time.utc(1999, 12, 31, 19), twz.time
|
||||
assert_equal Time.utc(2000), twz.utc
|
||||
assert_equal zone, twz.time_zone
|
||||
end
|
||||
|
||||
def test_iso8601_with_invalid_string
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
|
||||
|
@ -386,6 +403,99 @@ class TimeZoneTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_rfc3339
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
twz = zone.rfc3339("1999-12-31T14:00:00-10:00")
|
||||
assert_equal Time.utc(1999, 12, 31, 19), twz.time
|
||||
assert_equal Time.utc(2000), twz.utc
|
||||
assert_equal zone, twz.time_zone
|
||||
end
|
||||
|
||||
def test_rfc3339_with_fractional_seconds
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
twz = zone.iso8601("1999-12-31T14:00:00.750-10:00")
|
||||
assert_equal 750000, twz.time.usec
|
||||
assert_equal Time.utc(1999, 12, 31, 19, 0, 0 + Rational(3, 4)), twz.time
|
||||
assert_equal Time.utc(2000, 1, 1, 0, 0, 0 + Rational(3, 4)), twz.utc
|
||||
assert_equal zone, twz.time_zone
|
||||
end
|
||||
|
||||
def test_rfc3339_with_missing_time
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
|
||||
exception = assert_raises(ArgumentError) do
|
||||
zone.rfc3339("1999-12-31")
|
||||
end
|
||||
|
||||
assert_equal "invalid date", exception.message
|
||||
end
|
||||
|
||||
def test_rfc3339_with_missing_offset
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
|
||||
exception = assert_raises(ArgumentError) do
|
||||
zone.rfc3339("1999-12-31T19:00:00")
|
||||
end
|
||||
|
||||
assert_equal "invalid date", exception.message
|
||||
end
|
||||
|
||||
def test_rfc3339_with_invalid_string
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
|
||||
exception = assert_raises(ArgumentError) do
|
||||
zone.rfc3339("foobar")
|
||||
end
|
||||
|
||||
assert_equal "invalid date", exception.message
|
||||
end
|
||||
|
||||
def test_rfc3339_with_old_date
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
twz = zone.rfc3339("1883-12-31T19:00:00-05:00")
|
||||
assert_equal [0, 0, 19, 31, 12, 1883], twz.to_a[0, 6]
|
||||
assert_equal zone, twz.time_zone
|
||||
end
|
||||
|
||||
def test_rfc3339_far_future_date_with_time_zone_offset_in_string
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
twz = zone.rfc3339("2050-12-31T19:00:00-10:00") # i.e., 2050-01-01 05:00:00 UTC
|
||||
assert_equal [0, 0, 0, 1, 1, 2051], twz.to_a[0, 6]
|
||||
assert_equal zone, twz.time_zone
|
||||
end
|
||||
|
||||
def test_rfc3339_should_not_black_out_system_timezone_dst_jump
|
||||
with_env_tz("EET") do
|
||||
zone = ActiveSupport::TimeZone["Pacific Time (US & Canada)"]
|
||||
twz = zone.rfc3339("2012-03-25T03:29:00-07:00")
|
||||
assert_equal [0, 29, 3, 25, 3, 2012], twz.to_a[0, 6]
|
||||
end
|
||||
end
|
||||
|
||||
def test_rfc3339_should_black_out_app_timezone_dst_jump
|
||||
with_env_tz("EET") do
|
||||
zone = ActiveSupport::TimeZone["Pacific Time (US & Canada)"]
|
||||
twz = zone.rfc3339("2012-03-11T02:29:00-08:00")
|
||||
assert_equal [0, 29, 3, 11, 3, 2012], twz.to_a[0, 6]
|
||||
end
|
||||
end
|
||||
|
||||
def test_rfc3339_doesnt_use_local_dst
|
||||
with_env_tz "US/Eastern" do
|
||||
zone = ActiveSupport::TimeZone["UTC"]
|
||||
twz = zone.rfc3339("2013-03-10T02:00:00Z")
|
||||
assert_equal Time.utc(2013, 3, 10, 2, 0, 0), twz.time
|
||||
end
|
||||
end
|
||||
|
||||
def test_rfc3339_handles_dst_jump
|
||||
with_env_tz "US/Eastern" do
|
||||
zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
||||
twz = zone.iso8601("2013-03-10T02:00:00-05:00")
|
||||
assert_equal Time.utc(2013, 3, 10, 3, 0, 0), twz.time
|
||||
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")
|
||||
|
|
Loading…
Reference in a new issue