Ticket #10982: time_zone_attributes_2.diff
| File time_zone_attributes_2.diff, 11.3 kB (added by technoweenie, 5 months ago) |
|---|
-
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.in_current_time_zone, record.written_on 147 assert_kind_of ActiveSupport::TimeWithZone, record.written_on 148 end 149 end 150 151 def test_setting_time_zone_aware_attribute_to_utc 152 in_time_zone "Pacific Time (US & Canada)" do 153 utc_time = Time.utc(2008, 1, 1) 154 record = @target.new 155 record.written_on = utc_time 156 assert_equal utc_time.in_current_time_zone, record.written_on 157 end 158 end 159 160 def test_setting_time_zone_aware_attribute_to_utc_time 161 in_time_zone "Pacific Time (US & Canada)" do 162 utc_time = Time.utc(2008, 1, 1) 163 record = @target.new 164 record.written_on = utc_time 165 assert_equal utc_time.in_current_time_zone, record.written_on 166 end 167 end 168 169 def test_setting_time_zone_aware_attribute_in_other_time_zone 170 utc_time = Time.utc(2008, 1, 1) 171 cst_time = utc_time.in_time_zone("Central Time (US & Canada)") 172 in_time_zone "Pacific Time (US & Canada)" do 173 record = @target.new 174 record.written_on = cst_time 175 assert_equal utc_time.in_current_time_zone, record.written_on 176 end 177 end 178 179 def test_setting_time_zone_aware_attribute_in_current_time_zone 180 utc_time = Time.utc(2008, 1, 1) 181 in_time_zone "Pacific Time (US & Canada)" do 182 record = @target.new 183 record.written_on = utc_time.in_current_time_zone 184 assert_equal utc_time.in_current_time_zone, record.written_on 185 end 186 end 141 187 142 188 private 143 189 def time_related_columns_on_topic 144 190 Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&:name) 145 191 end 192 193 def in_time_zone(zone) 194 old_zone = Time.zone 195 old_tz = ActiveRecord::Base.time_zone_aware_attributes 196 197 Time.zone = zone ? TimeZone[zone] : nil 198 ActiveRecord::Base.time_zone_aware_attributes = !zone.nil? 199 yield 200 ensure 201 Time.zone = old_zone 202 ActiveRecord::Base.time_zone_aware_attributes = old_tz 203 end 146 204 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 941 ActiveRecord::Base.default_timezone = :utc 942 Time.zone = TimeZone[-28800] 943 attributes = { 944 "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", 945 "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" 946 } 947 topic = Topic.find(1) 948 topic.attributes = attributes 949 assert_equal Time.utc(2004, 6, 24, 23, 24, 0).in_current_time_zone, topic.written_on 950 ensure 951 ActiveRecord::Base.default_timezone = :local 952 Time.zone = nil 953 end 954 927 955 def test_multiparameter_attributes_on_time_with_empty_seconds 928 956 attributes = { 929 957 "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 2471 2471 2472 2472 # Includes an ugly hack for Time.local instead of Time.new because the latter is reserved by Time itself. 2473 2473 def instantiate_time_object(*values) 2474 @@default_timezone == :utc ? Time.utc(*values) : Time.local(*values) 2474 if Time.zone 2475 Time.local(*values).change_time_zone_to_current 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) -
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