Ticket #10982: time_zone_attributes_3.diff
| File time_zone_attributes_3.diff, 16.1 kB (added by gbuesing, 5 months ago) |
|---|
-
activesupport/test/time_zone_test.rb
old new 128 128 assert TimeZone.us_zones.include?(TimeZone["Hawaii"]) 129 129 assert !TimeZone.us_zones.include?(TimeZone["Kuala Lumpur"]) 130 130 end 131 132 def test_new 133 time = TimeZone["Hawaii"].new(2007, 2, 5, 15, 30, 45) 134 assert_equal Time.utc(2007, 2, 5, 15, 30, 45), time.time 135 assert_equal TimeZone["Hawaii"], time.time_zone 136 end 131 137 end 132 138 -
activesupport/test/core_ext/time_ext_test.rb
old new 459 459 assert_equal 86_400.0, Time.utc(2000, 1, 2) - ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1), TimeZone['UTC'] ) 460 460 end 461 461 462 def test_time_created_with_local_constructor_cannot_represent_times_during_hour_skipped_by_dst 463 with_env_tz 'US/Eastern' do 464 # On Apr 2 2006 at 2:00AM in US, clocks were moved forward to 3:00AM. 465 # Therefore, 2AM EST doesn't exist for this date; Time.local fails over to 3:00AM EDT 466 assert_equal Time.local(2006, 4, 2, 3), Time.local(2006, 4, 2, 2) 467 assert Time.local(2006, 4, 2, 2).dst? 468 end 469 end 470 462 471 protected 463 472 def with_env_tz(new_tz = 'US/Eastern') 464 473 old_tz, ENV['TZ'] = ENV['TZ'], new_tz -
activesupport/lib/active_support/values/time_zone.rb
old new 174 174 def to_s 175 175 "(UTC#{formatted_offset}) #{name}" 176 176 end 177 178 # Method for creating new ActiveSupport::TimeWithZone instance in time zone of self. Example: 179 # 180 # Time.zone = "Hawaii" # => "Hawaii" 181 # Time.zone.new(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00 182 def new(*args) 183 Time.utc_time(*args).change_time_zone(self) 184 end 177 185 178 186 begin # the following methods depend on the tzinfo gem 179 187 require_library_or_gem "tzinfo" unless Object.const_defined?(:TZInfo) -
activesupport/lib/active_support/core_ext/time/zones.rb
old new 9 9 end 10 10 11 11 module ClassMethods 12 attr_accessor :zone_default 13 12 14 def zone 13 Thread.current[:time_zone] 15 Thread.current[:time_zone] || zone_default 14 16 end 15 17 16 18 # Sets a global default time zone, separate from the system time zone in ENV['TZ']. -
activerecord/test/cases/attribute_methods_test.rb
old new 14 14 ActiveRecord::Base.attribute_method_suffix *@old_suffixes 15 15 end 16 16 17 18 17 def test_match_attribute_method_query_returns_match_data 19 18 assert_not_nil md = @target.match_attribute_method?('title=') 20 19 assert_equal 'title', md.pre_match … … 97 96 def test_only_time_related_columns_are_meant_to_be_cached_by_default 98 97 expected = %w(datetime timestamp time date).sort 99 98 assert_equal expected, ActiveRecord::Base.attribute_types_cached_by_default.map(&:to_s).sort 100 end99 end 101 100 102 101 def test_declaring_attributes_as_cached_adds_them_to_the_attributes_cached_by_default 103 102 default_attributes = Topic.cached_attributes … … 138 137 end 139 138 end 140 139 end 140 141 def test_time_attributes_are_retrieved_in_current_time_zone 142 in_time_zone "Pacific Time (US & Canada)" do 143 utc_time = Time.utc(2008, 1, 1) 144 record = @target.new 145 record[:written_on] = utc_time 146 assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time 147 assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone 148 assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone 149 assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly 150 end 151 end 152 153 def test_setting_time_zone_aware_attribute_to_utc 154 in_time_zone "Pacific Time (US & Canada)" do 155 utc_time = Time.utc(2008, 1, 1) 156 record = @target.new 157 record.written_on = utc_time 158 assert_equal utc_time, record.written_on 159 assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone 160 assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time 161 end 162 end 163 164 def test_setting_time_zone_aware_attribute_in_other_time_zone 165 utc_time = Time.utc(2008, 1, 1) 166 cst_time = utc_time.in_time_zone("Central Time (US & Canada)") 167 in_time_zone "Pacific Time (US & Canada)" do 168 record = @target.new 169 record.written_on = cst_time 170 assert_equal utc_time, record.written_on 171 assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone 172 assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time 173 end 174 end 175 176 def test_setting_time_zone_aware_attribute_in_current_time_zone 177 utc_time = Time.utc(2008, 1, 1) 178 in_time_zone "Pacific Time (US & Canada)" do 179 record = @target.new 180 record.written_on = utc_time.in_current_time_zone 181 assert_equal utc_time, record.written_on 182 assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone 183 assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time 184 end 185 end 141 186 142 187 private 143 188 def time_related_columns_on_topic 144 189 Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&:name) 145 190 end 191 192 def in_time_zone(zone) 193 old_zone = Time.zone 194 old_tz = ActiveRecord::Base.time_zone_aware_attributes 195 196 Time.zone = zone ? TimeZone[zone] : nil 197 ActiveRecord::Base.time_zone_aware_attributes = !zone.nil? 198 yield 199 ensure 200 Time.zone = old_zone 201 ActiveRecord::Base.time_zone_aware_attributes = old_tz 202 end 146 203 end -
activerecord/test/cases/base_test.rb
old new 924 924 assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on 925 925 end 926 926 927 def test_multiparameter_attributes_on_time_with_utc 928 ActiveRecord::Base.default_timezone = :utc 929 attributes = { 930 "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", 931 "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" 932 } 933 topic = Topic.find(1) 934 topic.attributes = attributes 935 assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on 936 ensure 937 ActiveRecord::Base.default_timezone = :local 938 end 939 940 def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes 941 ActiveRecord::Base.time_zone_aware_attributes = true 942 ActiveRecord::Base.default_timezone = :utc 943 Time.zone = TimeZone[-28800] 944 attributes = { 945 "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", 946 "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" 947 } 948 topic = Topic.find(1) 949 topic.attributes = attributes 950 assert_equal Time.utc(2004, 6, 24, 23, 24, 0), topic.written_on 951 assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on.time 952 assert_equal Time.zone, topic.written_on.time_zone 953 ensure 954 ActiveRecord::Base.time_zone_aware_attributes = false 955 ActiveRecord::Base.default_timezone = :local 956 Time.zone = nil 957 end 958 959 def test_multiparameter_attributes_on_time_with_skip_time_zone_conversion_for_attributes 960 ActiveRecord::Base.time_zone_aware_attributes = true 961 ActiveRecord::Base.default_timezone = :utc 962 Time.zone = TimeZone[-28800] 963 Topic.skip_time_zone_conversion_for_attributes = [:written_on] 964 attributes = { 965 "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", 966 "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" 967 } 968 topic = Topic.find(1) 969 topic.attributes = attributes 970 assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on 971 assert_equal false, topic.written_on.respond_to?(:time_zone) 972 ensure 973 ActiveRecord::Base.time_zone_aware_attributes = false 974 ActiveRecord::Base.default_timezone = :local 975 Time.zone = nil 976 Topic.skip_time_zone_conversion_for_attributes = [] 977 end 978 927 979 def test_multiparameter_attributes_on_time_with_empty_seconds 928 980 attributes = { 929 981 "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", -
activerecord/lib/active_record/attribute_methods.rb
old new 8 8 base.attribute_method_suffix(*DEFAULT_SUFFIXES) 9 9 base.cattr_accessor :attribute_types_cached_by_default, :instance_writer => false 10 10 base.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT 11 base.cattr_accessor :time_zone_aware_attributes, :instance_writer => false 12 base.time_zone_aware_attributes = false 13 base.cattr_accessor :skip_time_zone_conversion_for_attributes, :instance_writer => false 14 base.skip_time_zone_conversion_for_attributes = [] 11 15 end 12 16 13 17 # Declare and check for suffixed attribute methods. … … 64 68 unless instance_method_already_implemented?(name) 65 69 if self.serialized_attributes[name] 66 70 define_read_method_for_serialized_attribute(name) 71 elsif create_time_zone_conversion_attribute?(name, column) 72 define_read_method_for_time_zone_conversion(name) 67 73 else 68 74 define_read_method(name.to_sym, name, column) 69 75 end 70 76 end 71 77 72 78 unless instance_method_already_implemented?("#{name}=") 73 define_write_method(name.to_sym) 79 if create_time_zone_conversion_attribute?(name, column) 80 define_write_method_for_time_zone_conversion(name) 81 else 82 define_write_method(name.to_sym) 83 end 74 84 end 75 85 76 86 unless instance_method_already_implemented?("#{name}?") … … 121 131 @@attribute_method_suffixes ||= [] 122 132 end 123 133 134 def create_time_zone_conversion_attribute?(name, column) 135 time_zone_aware_attributes && !skip_time_zone_conversion_for_attributes.include?(name.to_sym) && [:datetime, :timestamp].include?(column.type) 136 end 137 124 138 # Define an attribute reader method. Cope with nil column. 125 139 def define_read_method(symbol, attr_name, column) 126 140 cast_code = column.type_cast_code('v') if column … … 140 154 def define_read_method_for_serialized_attribute(attr_name) 141 155 evaluate_attribute_method attr_name, "def #{attr_name}; unserialize_attribute('#{attr_name}'); end" 142 156 end 157 158 def define_read_method_for_time_zone_conversion(attr_name) 159 method_body = <<-EOV 160 def #{attr_name}(reload = false) 161 cached = @attributes_cache['#{attr_name}'] 162 return cached if cached && !reload 163 time = read_attribute('#{attr_name}') 164 @attributes_cache['#{attr_name}'] = time.acts_like?(:time) ? time.in_current_time_zone : time 165 end 166 EOV 167 evaluate_attribute_method attr_name, method_body 168 end 143 169 144 170 # Define an attribute ? method. 145 171 def define_question_method(attr_name) … … 149 175 def define_write_method(attr_name) 150 176 evaluate_attribute_method attr_name, "def #{attr_name}=(new_value);write_attribute('#{attr_name}', new_value);end", "#{attr_name}=" 151 177 end 178 179 def define_write_method_for_time_zone_conversion(attr_name) 180 method_body = <<-EOV 181 def #{attr_name}=(time) 182 if time 183 time = time.to_time rescue time unless time.acts_like?(:time) 184 time = time.in_current_time_zone if time.acts_like?(:time) 185 end 186 write_attribute(:#{attr_name}, time) 187 end 188 EOV 189 evaluate_attribute_method attr_name, method_body, "#{attr_name}=" 190 end 152 191 153 192 # Evaluate the definition for an attribute related method 154 193 def evaluate_attribute_method(attr_name, method_definition, method_name=attr_name) … … 303 342 end 304 343 super 305 344 end 306 307 345 308 346 private 309 347 -
activerecord/lib/active_record/base.rb
old new 2470 2470 end 2471 2471 2472 2472 # Includes an ugly hack for Time.local instead of Time.new because the latter is reserved by Time itself. 2473 def instantiate_time_object(*values) 2474 @@default_timezone == :utc ? Time.utc(*values) : Time.local(*values) 2473 def instantiate_time_object(name, values) 2474 if Time.zone && !self.class.skip_time_zone_conversion_for_attributes.include?(name.to_sym) 2475 Time.zone.new(*values) 2476 else 2477 @@default_timezone == :utc ? Time.utc(*values) : Time.local(*values) 2478 end 2475 2479 end 2476 2480 2477 2481 def execute_callstack_for_multiparameter_attributes(callstack) … … 2483 2487 else 2484 2488 begin 2485 2489 value = if Time == klass 2486 instantiate_time_object( *values)2490 instantiate_time_object(name, values) 2487 2491 elsif Date == klass 2488 2492 begin 2489 2493 Date.new(*values) 2490 2494 rescue ArgumentError => ex # if Date.new raises an exception on an invalid date 2491 instantiate_time_object( *values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates2495 instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates 2492 2496 end 2493 2497 else 2494 2498 klass.new(*values) -
railties/lib/initializer.rb
old new 81 81 initialize_dependency_mechanism 82 82 initialize_whiny_nils 83 83 initialize_temporary_session_directory 84 initialize_time_zone 84 85 initialize_framework_settings 85 86 86 87 add_support_load_paths … … 316 317 end 317 318 end 318 319 320 def initialize_time_zone 321 if configuration.time_zone 322 Time.zone_default = TimeZone[configuration.time_zone] 323 if configuration.frameworks.include?(:active_record) 324 ActiveRecord::Base.time_zone_aware_attributes = true 325 ActiveRecord::Base.default_timezone = :utc 326 end 327 end 328 end 329 319 330 # Initializes framework-specific settings for each of the loaded frameworks 320 331 # (Configuration#frameworks). The available settings map to the accessors 321 332 # on each of the corresponding Base classes. … … 456 467 end 457 468 alias_method :breakpoint_server=, :breakpoint_server 458 469 470 # Sets the default time_zone. Setting this will enable time_zone 471 # awareness for ActiveRecord models and set the ActiveRecord default 472 # timezone to :utc. 473 attr_accessor :time_zone 474 459 475 # Create a new Configuration instance, initialized with the default 460 476 # values. 461 477 def initialize