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

Timecop handles GMT/UTC Time objects incorrectly #8

Closed
nogweii opened this issue Jun 3, 2010 · 14 comments
Closed

Timecop handles GMT/UTC Time objects incorrectly #8

nogweii opened this issue Jun 3, 2010 · 14 comments

Comments

@nogweii
Copy link

nogweii commented Jun 3, 2010

Timecop always calls Time#getlocal regardless if the time object passed to parse_time() is GMT or UTC.

If the passed in object is an instance of Time, why not just use it's values directly? Why call getlocal? Besides, for large scale distributed applications, each machine could be in different timezones, causing getlocal to return different values! (Granted, for mocking and testing, this scenario isn't likely.)

@nogweii
Copy link
Author

nogweii commented Jun 3, 2010

Looking now, this seems to be similar (if not the same?) as issue #7.

@jtrupiano
Copy link
Collaborator

Issue #7 occurs due to the fact that calling #utc on an instance of Time actually mutates the Time instance. I'm pretty sure that I know what the workaround to it is, I just haven't gotten around to it.

Calling #getlocal regardless allowed me to normalize the "figure out what time is being passed in in the first place" problem. Furthermore, iirc, it helps me to deal with DST (which is a huge PITA).

Are you actually seeing any incorrect behavior? Timecop is a testing library after all. I'm not sure that the concerns you have (different time zones on different machines) are particularly relevant.

@nogweii
Copy link
Author

nogweii commented Jun 4, 2010

Yeah, I just brought that up in hopes of shoring up my arguement.

But I am experiencing what I consider a bug. I call TimeCop.freeze(Time.gmt(...)) and I expected it to be GMT time. I choose to call gmt rather than local so that I know that the time (and potentially, the date) is correct, regardless of where the computer is, or where the tests are run. Instead, due to the call to #getlocal, the frozen time is 4 hours behind the GMT time, causing my tests to be incorrect.

Now, if DST is such a pain (I haven't done enough time related testing to really know) and the solution is to call #getlocal, why not also add in a case for GMT/UTC times? Time provides a #gmt? method you could call, and my idea is, if it returns true, just use the pass Time object directly, rather than calling #getlocal.

If you want, I could write the patch myself.

@jtrupiano
Copy link
Collaborator

It wouldn't hurt to write up the patch yourself. I don't see myself being able to get to this anytime soon.

@ajsharp
Copy link

ajsharp commented Dec 16, 2010

I agree with evaryont, this is a major issue for us as well. parse_time converts all Time objects passed to it to local system time, ignoring the time zone setting. This is especially important when testing rails apps where a time zone setting exists at the application level. When I do the following, I expect Timecop to freeze time at the utc time zone, but instead, freezes and returns a time object based on the timezone of my system, which is in PST:

Timecop.freeze(Time.utc(2010, 12, 12)) # => Sat Dec 11 19:00:00 -0500 2010 

Does this use case make sense? Also, is timecop trying to support the rails use-case, where application/user-specific time zone information is important?

@jtrupiano
Copy link
Collaborator

Yes, this use case makes sense. Honestly I've never used rails' time zone setting (also use UTC). I think that an older version of Timecop will actually behave properly for your use case. I think I changed the behavior between 0.3.1 and 0.3.4 (0.3.2 and 0.3.3 were yanked) when I made efforts to properly handle DST (which is a bitch to support across timezones). Try 0.3.1 and also try 0.2.0. I'm curious if those work for you.

@d11wtq
Copy link

d11wtq commented Jun 19, 2011

This was a deal-breaker for me. My specs were failing because I'm in Melbourne/Australia, and I needed to test something at Time.utc(2009, 3, 9), which logically is midnight, 9th March 2009, right? Or 1am if you're using Timecop. I don't understand the need for using local time, rather than just using the time given. That's where this issue is arising. DST between timezones.

I've ended up with the K.I.S.S approach, that granted, might not work for everyone, but works for us where Timecop broke our tests:

class Time
  class << self
    attr_accessor :mock_time

    def now_with_mock_time
      @mock_time || now_without_mock_time
    end

    alias_method_chain :now, :mock_time

    def be(a_time)
      raise ArgumentError, "Time.be requires a block, but none was given" unless block_given?

      original_mock_time = @mock_time
      @mock_time = a_time
      yield
    ensure
      @mock_time = original_mock_time
    end
  end
end

When the time is frozen with this approach, Time, DateTime and Date all see the current time is whatever it is frozen at, at least in ruby 1.9.2.

I hope this gets fixed.

@h0jeZvgoxFepBQ2C
Copy link

Yeah please fix this, thats nasty..!

@cmeiklejohn
Copy link

+1

@swalberg
Copy link

Just as another datapoint, my tests started failing this morning after the time change. Reverting to 0.3.1 fixed it.

I freeze to a GMT time and run some jobs, then check the dates. DateTime.now.in_time_zone("UTC") changed when my computer's clock changed.

@smlsml
Copy link

smlsml commented Mar 13, 2012

Our tests also starting failing today:

Timecop.freeze(Time.utc(2011, 1, 1, 0, 0, 0))
puts DateTime.now.utc

2010-12-31T23:00:00+00:00 # wtf?

@cthulhu
Copy link

cthulhu commented Apr 11, 2012

Is that fixed?

@travisjeffery
Copy link
Owner

I'm going to close this issue as it seems to not be going anywhere, if this is still a problem then please open a fresh issue and we can discuss.

@ksbek
Copy link

ksbek commented Sep 28, 2021

Is this fixed?

new_time = Time.utc(2016,10,28, 10, 24, 00)
Timecop.freeze(new_time)
t1 = Date.today.to_time.advance(days: -2)

t1 is 2016-10-26 00:00:00 +0100. Why +0100 is here?

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

No branches or pull requests