rails: :time doesn't follow the same dst behavior of :datetime

Steps to reproduce

begin
  require 'bundler/inline'
rescue LoadError => e
  $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
  raise e
end

gemfile(true) do
  source 'https://rubygems.org'
  gem 'activerecord', '>= 5.0.0.beta4'
  gem 'sqlite3'
end

require 'active_record'
require 'minitest/autorun'
require 'logger'

# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
ActiveRecord::Base.time_zone_aware_types << :time
ActiveRecord::Base.time_zone_aware_attributes = true

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
    t.time :time_offset_bug
  end

end

class Post < ActiveRecord::Base
end

class BugTest < Minitest::Test
  def test_offset_bug
    Time.zone = 'Brasilia'
    assert_equal "-03:00", Time.current.formatted_offset # this works

    post = Post.create!(time_offset_bug: "14:00")

    # this blows up
    assert_equal "-03:00", post.time_offset_bug.formatted_offset
    assert_equal "2000-01-01 17:00:00 UTC", post.time_offset_bug.utc.to_s
  end
end

Expected behavior

post.time_offset_bug.utc_offset should be -3 (and the time saved in the database should be saved in UTC)

Actual behavior

post.time_offset_bug.utc_offset is -2 and the time saved in the database isn’t saved in UTC.

System configuration

Rails 5.0.0.beta4(happens at master as well) ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 21 (15 by maintainers)

Most upvoted comments

Workaround

config/initializers/time_only.rb

class TimeOnlyType < ActiveRecord::Type::DateTime
  def cast(value)
    value.is_a?(::String) ? super("#{Date.today} #{value}") : super
  end
end

ActiveRecord::Type.register :time_only, TimeOnlyType

app/models/availability.rb

class Availability < ApplicationRecord
  attribute :starts_at, :time_only
  attribute :ends_at,   :time_only
end

Also just to clarify one last point before I log off, I would love to improve this behavior as I agree there is something unintuitive. I just don’t think there is an alternative that would work here.

On Mon, May 9, 2016, 12:30 PM Sean Griffin sean@seantheprogrammer.com wrote:

No. I mean not using time zone aware attributes on fields where it’s not needed – or setting Time.zone to UTC

On Mon, May 9, 2016, 12:27 PM Bruno Zanchet notifications@github.com wrote:

hey @sgrif https://github.com/sgrif, thanks again for taking the time to discuss this. Here’s what happens if I try to save it as UTC:

class BugTest < Minitest::Test def test_dst_bug Time.use_zone(‘Brasilia’) do # GMT-3

  now = Time.current # 13h30
  post = Post.create!(the_time: now.utc) # 16:30 UTC
  post.reload # it's saved as 16:30 UTC
  assert_equal 13, post.the_time.hour # fail: Expected: 13, Actual: 14
end

endend

I wish this workaround worked, but it only highlights the fact that 1/1/2000 doesn’t work every time. Is this what you meant by it’s likely best to use UTC?

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/rails/rails/issues/24880#issuecomment-217915026