diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index d3fd760159..db46ce4f4d 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 2e85d14579..d93c1148c4 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 @@ module ActiveSupport #:nodoc: 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 4fa1b5aafd..f69bdba127 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 @@ class DateTimeExtCalculationsTest < Test::Unit::TestCase 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')