Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timezone problem when casting time field #46220

Closed
bvicenzo opened this issue Oct 10, 2022 · 2 comments
Closed

Timezone problem when casting time field #46220

bvicenzo opened this issue Oct 10, 2022 · 2 comments

Comments

@bvicenzo
Copy link

Steps to reproduce

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "rails", github: "rails/rails", branch: "main"
end

require "active_support"
require "active_support/core_ext/object/blank"
require "minitest/autorun"

class BugTest < Minitest::Test
  def test_time_zone
    Time.zone = 'Brasilia'
    assert Time.zone.local(2007, 2, 10, 15, 30, 45).to_s.end_with?('-0300')
    assert Time.zone.parse('2007-02-10 15:30:45').to_s.end_with?('-0300')
    assert Time.zone.at(1171139445).to_s.end_with?('-0300')
    assert Time.zone.now.to_s.end_with?('-0300')
    assert Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone.to_s.end_with?('-0300')
  end
end

Expected behavior

Looking for TimeWithZone doc, I understood that this should return time in the defined timezone.

Time.zone = 'Eastern Time (US & Canada)'        # => 'Eastern Time (US & Canada)'
Time.zone.local(2007, 2, 10, 15, 30, 45)        # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
Time.zone.parse('2007-02-10 15:30:45')          # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
Time.zone.at(1171139445)                        # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
Time.zone.now                                   # => Sun, 18 May 2008 13:07:55.754107581 EST -05:00
Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone  # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00

Actual behavior

However, what I see is Time.zone.now returning a different timezone from others. As docs.

image

image

Shouldn't they all return the same timezone?

I realized that when I'm using a time field and it started to show my time aways 1 hour ahead.
And I saw that is uses Time.local to cast:

::Time.local(year, mon, mday, hour, min, sec, microsec) rescue nil

It seems that all methods, except Time.zone.now are using brazilian summer time instead of use brazilian time.

System configuration

Rails version: 7.0.3.1

Ruby version: 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux-musl]

@hbontempo-br
Copy link

Hi @bvicenzo!

I know this is strange and confusing, but the behavior is correct.
The normal timezone for Brazil is -03:00, but in 2007-02-10 Brazil was in the -02:00 timezone because in this date Brazil was using a DST (summer time).

image

Source: https://pt.wikipedia.org/wiki/Lista_de_per%C3%ADodos_em_que_vigorou_o_horário_de_verão_no_Brasil

@bvicenzo
Copy link
Author

Hi @hbontempo-br!

Thanks for the answer.

That's true!!!

Then I realized what would be happening to me...

As I said before, I'm using a time field, and before, and it casts the value to a date time field:

ActiveModel::Type::Time.new.cast('10:00') # => 2000-01-01 10:00:00 -0200

And this could confuse me. I'll keep investigating my problem.

Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants