Permalink
Browse files

Proposed solution for SQL TIME('24:00') roundtrips

This extension can be loaded optionally by manual require "active_support/core_ext/time/twenty_four"
Please review and comment #7125.
  • Loading branch information...
1 parent 1b2a7ba commit 65958d37ba1f95619b30a9cc4bc2b1bfd469eb34 @avit committed Jul 22, 2012
@@ -0,0 +1,50 @@
+# Handles conversion of SQL time columns with values of "24:00" for roundtrips
+# to the database.
+#
+# time = Time.now.beginning_of_day # => Sun Jul 22 00:00:00 PDT 2012
+# time.to_s(:db) # => "2012-07-22 00:00:00"
+#
+# time.twenty_four # => Sun Jul 22 00:00:00 PDT 2012
+# time.to_s(:db) # => "2012-07-22 24:00:00"
+#
+# time = Time.parse("24:00:00") # => Sun Jul 22 00:00:00 PDT 2012
+# time.twenty_four? # => true
+# time.to_s(:db) # => "2012-07-22 24:00:00"
+#
+# Requiring this optional file overwrites the standard
+# <tt>Time::DATE_FORMATS[:db]</tt> conversion to handle the '24:00' case.
+class Time
+ def twenty_four=(flag)
+ @twenty_four = flag && self == beginning_of_day
+ self
+ end
+
+ def twenty_four
+ self.twenty_four = true
+ self
+ end
+
+ def twenty_four?
+ @twenty_four ||= false
+ end
+
+ class << self
+ def new(*args)
+ super(*args).tap do |t|
+ t.twenty_four = [24 == args[3].to_i,
+ 0 == args[4].to_i,
+ 0 == args[5].to_i].all?
+ end
+ end
+
+ def parse_with_twenty_four(string)
+ parse_without_twenty_four(string).tap do |t|
+ t.twenty_four = !!(/24:00(:00)?/ =~ string)
+ end
+ end
+ alias_method :parse_without_twenty_four, :parse
+ alias_method :parse, :parse_with_twenty_four
+ end
+end
+
+Time::DATE_FORMATS[:db] = lambda { |t| t.twenty_four? ? (t - 1.day).strftime('%Y-%m-%d 24:00:00') : t.strftime('%Y-%m-%d %H:%M:%S') }
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'active_support/time'
+require 'active_support/core_ext/time/twenty_four'
class TimeExtCalculationsTest < ActiveSupport::TestCase
def test_seconds_since_midnight
@@ -694,6 +695,16 @@ def test_time_with_datetime_fallback
end
end
+ def test_twenty_four_hours_db_format
+ Time.stubs(:now).returns(Time.utc(2012))
+ assert_equal "2012-01-01 24:00:00", Time.parse('24:00').to_s(:db)
+ assert_equal "2012-01-01 00:00:00", Time.parse('00:00').to_s(:db)
+ assert_equal "2012-01-01 24:00:00", Time.new(2012, 1, 1, 24, 0, 0).to_s(:db)
+ assert_equal "2012-01-01 00:00:00", Time.new(2012, 1, 1, 0, 0, 0).to_s(:db)
+ assert_equal "2011-12-31 24:00:00", Time.new(2012, 1, 1, 0, 0, 0).twenty_four.to_s(:db)
+ assert_equal "2012-01-01 12:34:56", Time.new(2012, 1, 1, 12, 34, 56).twenty_four.to_s(:db)
+ end
+
def test_utc_time
assert_equal Time.utc_time(2005, 2, 21, 17, 44, 30), Time.utc(2005, 2, 21, 17, 44, 30)
assert_equal Time.utc_time(2039, 2, 21, 17, 44, 30), DateTime.civil(2039, 2, 21, 17, 44, 30, 0)

0 comments on commit 65958d3

Please sign in to comment.