diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index d3fd760159f54b0471f3d126489d75c359e39199..db46ce4f4d79b20185f9d3b2a1f89f01cc90eaba 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Introducing DateTime #utc, #utc? and #utc_offset, for duck-typing compatibility with Time. Closes #10002 [Geoff Buesing] + * Time#to_json uses Numeric#to_utc_offset_s to output a cross-platform-consistent representation without having to convert to DateTime. References #9750 [Geoff Buesing] * Refactor number-to-HH:MM-string conversion logic from TimeZone#formatted_offset to a reusable Numeric#to_utc_offset_s method. [Geoff Buesing] diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb index 2e85d145799824308b1bfa0fa8dd4ac798941fb0..d93c1148c4add623a6045064ae7d397ae1877c8d 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -71,6 +71,26 @@ def beginning_of_day def end_of_day change(:hour => 23, :min => 59, :sec => 59) end + + # Adjusts DateTime to UTC by adding its offset value; offset is set to 0 + # + # Example: + # + # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600 + # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000 + def utc + new_offset(0) + end + + # Returns true if offset == 0 + def utc? + offset == 0 + end + + # Returns the offset value in seconds + def utc_offset + (offset * 86400).to_i + end end end end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 4fa1b5aafd10204963af3547e22eabe6f307148f..f69bdba1279436facda89a8d7d855624e024bd89 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -219,6 +219,28 @@ def test_local_offset assert_equal Rational(-6, 24), DateTime.local_offset end end + + def test_utc? + assert_equal true, DateTime.civil(2005, 2, 21, 10, 11, 12).utc? + assert_equal true, DateTime.civil(2005, 2, 21, 10, 11, 12, 0).utc? + assert_equal false, DateTime.civil(2005, 2, 21, 10, 11, 12, 0.25).utc? + assert_equal false, DateTime.civil(2005, 2, 21, 10, 11, 12, -0.25).utc? + end + + def test_utc_offset + assert_equal 0, DateTime.civil(2005, 2, 21, 10, 11, 12).utc_offset + assert_equal 0, DateTime.civil(2005, 2, 21, 10, 11, 12, 0).utc_offset + assert_equal 21600, DateTime.civil(2005, 2, 21, 10, 11, 12, 0.25).utc_offset + assert_equal( -21600, DateTime.civil(2005, 2, 21, 10, 11, 12, -0.25).utc_offset ) + assert_equal( -18000, DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-5, 24)).utc_offset ) + end + + def test_utc + assert_equal DateTime.civil(2005, 2, 21, 16, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc + assert_equal DateTime.civil(2005, 2, 21, 15, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-5, 24)).utc + assert_equal DateTime.civil(2005, 2, 21, 10, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, 0).utc + assert_equal DateTime.civil(2005, 2, 21, 9, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(1, 24)).utc + end protected def with_timezone(new_tz = 'US/Eastern')