diff options
author | Andrew White <andrew.white@unboxed.co> | 2017-03-03 20:12:47 +0000 |
---|---|---|
committer | Andrew White <andrew.white@unboxed.co> | 2017-03-03 21:53:13 +0000 |
commit | 08e05d4a49c1ba1327e3e6821eba1f0c93361ab2 (patch) | |
tree | c69d4fe566ad5d0c86f31220aeba05e6710682b4 | |
parent | f61062c70f27059375a927caadfee458b7037c20 (diff) | |
download | rails-08e05d4a49c1ba1327e3e6821eba1f0c93361ab2.tar.gz rails-08e05d4a49c1ba1327e3e6821eba1f0c93361ab2.tar.bz2 rails-08e05d4a49c1ba1327e3e6821eba1f0c93361ab2.zip |
Add `Time.rfc3339` parsing method
The `Time.xmlschema` and consequently its alias `iso8601` accepts
timestamps without a offset in contravention of the RFC 3339
standard. This method enforces that constraint and raises an
`ArgumentError` if it doesn't.
-rw-r--r-- | activesupport/CHANGELOG.md | 8 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/time/calculations.rb | 23 | ||||
-rw-r--r-- | activesupport/test/core_ext/time_ext_test.rb | 31 |
3 files changed, 62 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 8fc22a614d..3cfca555e3 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,11 @@ +* Add `Time.rfc3339` parsing method + + The `Time.xmlschema` and consequently its alias `iso8601` accepts timestamps + without a offset in contravention of the RFC 3339 standard. This method + enforces that constraint and raises an `ArgumentError` if it doesn't. + + *Andrew White* + * Add `ActiveSupport::TimeZone.rfc3339` parsing method Previously there was no way to get a RFC 3339 timestamp into a specific diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index cbdcb86d6d..7b7aeef25a 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -53,6 +53,29 @@ class Time end alias_method :at_without_coercion, :at alias_method :at, :at_with_coercion + + # Creates a +Time+ instance from an RFC 3339 string. + # + # Time.rfc3339('1999-12-31T14:00:00-10:00') # => 2000-01-01 00:00:00 -1000 + # + # If the time or offset components are missing then an +ArgumentError+ will be raised. + # + # Time.rfc3339('1999-12-31') # => ArgumentError: invalid date + def rfc3339(str) + parts = Date._rfc3339(str) + + raise ArgumentError, "invalid date" if parts.empty? + + 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) + ) + end end # Returns the number of seconds since 00:00:00. diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index a399e36dc9..8b60494143 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -910,6 +910,37 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase def test_all_year assert_equal Time.local(2011, 1, 1, 0, 0, 0)..Time.local(2011, 12, 31, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_year end + + def test_rfc3339_parse + time = Time.rfc3339("1999-12-31T19:00:00.125-05:00") + + assert_equal 1999, time.year + assert_equal 12, time.month + assert_equal 31, time.day + assert_equal 19, time.hour + assert_equal 0, time.min + assert_equal 0, time.sec + assert_equal 125000, time.usec + assert_equal(-18000, time.utc_offset) + + exception = assert_raises(ArgumentError) do + Time.rfc3339("1999-12-31") + end + + assert_equal "invalid date", exception.message + + exception = assert_raises(ArgumentError) do + Time.rfc3339("1999-12-31T19:00:00") + end + + assert_equal "invalid date", exception.message + + exception = assert_raises(ArgumentError) do + Time.rfc3339("foobar") + end + + assert_equal "invalid date", exception.message + end end class TimeExtMarshalingTest < ActiveSupport::TestCase |