aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/environment.rb1
-rw-r--r--lib/timezone_fixes.rb25
-rw-r--r--spec/libs/timezone_fixes.rb81
3 files changed, 107 insertions, 0 deletions
diff --git a/config/environment.rb b/config/environment.rb
index f3a1b1668..f409936d1 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -131,6 +131,7 @@ end
require 'tmail_extensions.rb'
require 'activesupport_cache_extensions.rb'
require 'public_body_categories.rb'
+require 'timezone_fixes.rb'
# XXX temp debug for SQL logging production sites
#ActiveRecord::Base.logger = Logger.new(STDOUT)
diff --git a/lib/timezone_fixes.rb b/lib/timezone_fixes.rb
new file mode 100644
index 000000000..b830ded4e
--- /dev/null
+++ b/lib/timezone_fixes.rb
@@ -0,0 +1,25 @@
+# Taken from
+# https://rails.lighthouseapp.com/projects/8994/tickets/2946
+# http://github.com/rails/rails/commit/6f97ad07ded847f29159baf71050c63f04282170
+
+# Otherwise times get stored wrong during British Summer Time
+
+# Hopefully fixed in later Rails. There is a test in spec/libs/timezone_fixes.rb
+
+# Monkeypatch!
+module ActiveRecord
+ module ConnectionAdapters # :nodoc:
+ module Quoting
+ def quoted_date(value)
+ value.to_s(:db)
+ if value.acts_like?(:time)
+ zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
+ value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
+ else
+ value
+ end.to_s(:db)
+ end
+ end
+ end
+end
+
diff --git a/spec/libs/timezone_fixes.rb b/spec/libs/timezone_fixes.rb
new file mode 100644
index 000000000..9ceb58a13
--- /dev/null
+++ b/spec/libs/timezone_fixes.rb
@@ -0,0 +1,81 @@
+# This is a test of the monkey patches in timezone_fixes.rb
+
+# We use EximLogDone here just as a totally random model that has a datetime type.
+
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe "when doing things with timezones" do
+
+ it "should preserve time objects with local time conversion to default timezone UTC" do
+ with_env_tz 'America/New_York' do
+ with_active_record_default_timezone :utc do
+ time = Time.local(2000)
+ exim_log_done = EximLogDone.create('last_stat' => time, 'filename' => 'dummy')
+ saved_time = EximLogDone.find(exim_log_done.id).last_stat
+ assert_equal time, saved_time
+ assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "EST"], time.to_a
+ assert_equal [0, 0, 5, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
+ end
+ end
+ end
+
+ it "should preserve time objects with time with zone conversion to default timezone UTC" do
+ with_env_tz 'America/New_York' do
+ with_active_record_default_timezone :utc do
+ Time.use_zone 'Central Time (US & Canada)' do
+ time = Time.zone.local(2000)
+ exim_log_done = EximLogDone.create('last_stat' => time, 'filename' => 'dummy')
+ saved_time = EximLogDone.find(exim_log_done.id).last_stat
+ assert_equal time, saved_time
+ assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
+ assert_equal [0, 0, 6, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
+ end
+ end
+ end
+ end
+
+ # XXX Couldn't get this test to work - but the other tests seem to detect presence of
+ # the monkey patch, so they will do for now.
+ #it "should preserve time objects with UTC time conversion to default timezone local" do
+ # with_env_tz 'America/New_York' do
+ # time = Time.utc(2000)
+ # exim_log_done = EximLogDone.create('last_stat' => time, 'filename' => 'dummy')
+ # saved_time = EximLogDone.find(exim_log_done.id).last_stat
+ # assert_equal time, saved_time
+ # assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], time.to_a
+ # assert_equal [0, 0, 19, 31, 12, 1999, 5, 365, false, "EST"], saved_time.to_a
+ # end
+ #end
+
+ it "should preserve time objects with time with zone conversion to default timezone local" do
+ with_env_tz 'America/New_York' do
+ with_active_record_default_timezone :local do
+ Time.use_zone 'Central Time (US & Canada)' do
+ time = Time.zone.local(2000)
+ exim_log_done = EximLogDone.create('last_stat' => time, 'filename' => 'dummy')
+ saved_time = EximLogDone.find(exim_log_done.id).last_stat
+ assert_equal time, saved_time
+ assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
+ assert_equal [0, 0, 1, 1, 1, 2000, 6, 1, false, "EST"], saved_time.to_a
+ end
+ end
+ end
+ end
+
+ protected
+ def with_env_tz(new_tz = 'US/Eastern')
+ old_tz, ENV['TZ'] = ENV['TZ'], new_tz
+ yield
+ ensure
+ old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
+ end
+
+ def with_active_record_default_timezone(zone)
+ old_zone, ActiveRecord::Base.default_timezone = ActiveRecord::Base.default_timezone, zone
+ yield
+ ensure
+ ActiveRecord::Base.default_timezone = old_zone
+ end
+end
+
+