Open trafium opened 3 months ago
Hello,
as a preliminary remark, a reminder that Time.parse(str)
does not care about time zones:
# ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-openbsd7.4]
require 'time'
ENV['TZ'] = 'Europe/Tallinn'
p Time.now
# 2024-03-26 01:19:30.188064864 +0200
p Time.parse("2012-10-28 02:59:00 EEST")
p Time.parse("2012-10-28 02:59:00 Europe/Tallinn")
# 2012-10-28 02:59:00 +0300
# 2012-10-28 02:59:00 +0300
p Time.parse("2012-10-28 02:59:00 Some/Where")
p Time.parse("2012-10-28 02:59:00 XXX")
# 2012-10-28 02:59:00 +0300
# 2012-10-28 02:59:00 +0300
ENV['TZ'] = 'Asia/Tokyo'
p Time.now
# 2024-03-26 08:19:30.18919636 +0900
p Time.parse("2012-10-28 02:59:00 EEST")
p Time.parse("2012-10-28 02:59:00 Europe/Tallinn")
# 2012-10-28 02:59:00 +0900
# 2012-10-28 02:59:00 +0900
p Time.parse("2012-10-28 02:59:00 Some/Where")
p Time.parse("2012-10-28 02:59:00 XXX")
# 2012-10-28 02:59:00 +0900
# 2012-10-28 02:59:00 +0900
Tinkering:
# ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-openbsd7.4]
require 'fugit'
ENV['TZ'] = 'Europe/Tallinn'
# approximating OP's situation...
p Fugit::Cron.parse("*/1 * * * *")
.next_time(Time.parse("2012-10-28 02:59:00 EEST")).to_t
# => 2012-10-28 03:00:00 +0300 ## because ENV TZ is Europe/Tallinn
p Fugit::Cron.parse("*/1 * * * *")
.next_time(Fugit.parse("2012-10-28 02:59:00 EEST")).to_t
# => 2012-10-28 10:00:00 +0200 ## off
p Fugit::Cron.parse("*/1 * * * *")
.next_time(Fugit.parse("2012-10-28 02:59:00 Europe/Tallin")).to_t
# => 2012-10-28 03:00:00 +0300 ## OK
##
#p Fugit::Cron.parse("*/1 * * * *")
# .next_time(Time.parse("2012-10-28 02:59:00 EEST") + 1.minute)
#p Fugit::Cron.parse("*/1 * * * *")
# .next_time(Time.parse("2012-10-28 02:59:00 EEST") + 60)
#p Fugit::Cron.parse("*/1 * * * *")
# .next_time(Fugit.parse("2012-10-28 02:59:00 EEST") + 60).to_t
p Fugit::Cron.parse("*/1 * * * *")
.next_time(Fugit.parse("2012-10-28 02:59:00 Europe/Tallin") + 60).to_t
# => 2012-10-28 03:01:00 +0300
#/Users/traf/.rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/et-orbi-1.2.11/lib/et-orbi/time.rb:82
# :in `initialize': Cannot determine timezone from "EEST" (ArgumentError)
##
#p Fugit::Cron.parse("*/1 * * * *")
# .next_time(Time.parse("2012-10-28 03:00:00 EEST")).to_t
p Fugit::Cron.parse("*/1 * * * *")
.next_time(Fugit.parse("2012-10-28 03:00:00 EEST")).to_t
# => 2012-10-28 10:01:00 +0200
p Fugit::Cron.parse("*/1 * * * *")
.next_time(Fugit.parse("2012-10-28 03:00:00 Europe/Tallinn")).to_t
# => ~/.gem/ruby/3.2.2/gems/et-orbi-1.2.11/lib/et-orbi/make.rb:65
# :in `make_time': Cannot turn nil to a ::EtOrbi::EoTime instance
# (ArgumentError)
# from ~/w/fugit/lib/fugit/cron.rb:247:in `next_time'
p Fugit.parse("2012-10-28 03:00:00 Europe/Tallinn")
# => nil
p EtOrbi.parse("2012-10-28 03:00:00 Europe/Tallinn")
# => ~/.gem/ruby/3.2.2/gems/tzinfo-2.0.6/lib/tzinfo/timezone.rb:525:in `period_for_local':
# 2012-10-28 03:00:00 is an ambiguous local time. (TZInfo::AmbiguousTime)
# from ~/.gem/ruby/3.2.2/gems/tzinfo-2.0.6/lib/tzinfo/timezone.rb:652:in `block in local_to_utc'
# from ~/.gem/ruby/3.2.2/gems/tzinfo-2.0.6/lib/tzinfo/timestamp.rb:144:in `for'
# from ~/.gem/ruby/3.2.2/gems/tzinfo-2.0.6/lib/tzinfo/timezone.rb:648:in `local_to_utc'
# from ~/.gem/ruby/3.2.2/gems/et-orbi-1.2.11/lib/et-orbi/make.rb:46:in `parse'
p (Fugit.parse("2012-10-28 02:59:00 Europe/Tallinn") + 60).to_t
# => 2012-10-28 03:00:00 +0300
##
#p Fugit::Cron.parse("*/1 * * * *")
# .next_time(Time.parse("2012-10-28 02:59:00 Europe/Tallinn") + 1.minute)
#p Fugit::Cron.parse("*/1 * * * *")
# .next_time(Time.parse("2012-10-28 02:59:00 Europe/Tallinn") + 60)
p Fugit::Cron.parse("*/1 * * * *")
.next_time(Fugit.parse("2012-10-28 02:59:00 Europe/Tallinn") + 60).to_t
# => 2012-10-28 03:01:00 +0300
Further tinkering:
This works:
require 'fugit'
ENV['TZ'] = 'Europe/Tallinn'
#c = Fugit.parse_cron('*/1 * * * *') # equivalent to
c = Fugit.parse_cron('* * * * *')
t = Fugit.parse('2012-10-28 02:59:00 Europe/Tallinn')
70.times do |i|
puts "%2d - %s" % [ i, t ? t.to_t.inspect : 'nil' ]
t = c.next_time(t)
end
It transitions smoothly:
...
58 - 2012-10-28 03:57:00 +0300
59 - 2012-10-28 03:58:00 +0300
60 - 2012-10-28 03:59:00 +0300
61 - 2012-10-28 03:00:00 +0200
62 - 2012-10-28 03:01:00 +0200
63 - 2012-10-28 03:02:00 +0200
...
But making it start at '2012-10-28 03:00:00 Europe/Tallinn'
instead of '2012-10-28 02:59:00 Europe/Tallinn'
has nil
for t
and it fails immediately. Fugit.parse('2023-10-28 03:00:00')
(in Europe/Tallinn) also returns nil
.
I need to find a way in fugit or et-orbi to return the right time when parsing an ambiguous timezone.
I will go on investigating tonight after work. Thanks for reporting that.
Thanks @jmettraux, I was unaware of that weird behaviour of Time.parse with time zones. Still trying to grasp what is going on exactly though.
But keeping that in mind, I found out that I can use Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") which gives me ActiveSupport::TimeWithZone
and it does not break in Fugit that way.
Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") + 1.minute
#=> Sun, 28 Oct 2012 03:00:00.000000000 EEST +03:00
(Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") + 1.minute).zone
#=> "EEST"
(Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") + 1.minute).dst?
#=> true
(Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") + 1.minute) == (Time.parse("2012-10-28 02:59:00 Europe/Tallinn") + 1.minute)
#=> true
(Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") + 1.minute).zone == (Time.parse("2012-10-28 02:59:00 Europe/Tallinn") + 1.minute).zone
#=> true
(Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") + 1.minute).dst? == (Time.parse("2012-10-28 02:59:00 Europe/Tallinn") + 1.minute).dst?
#=> true
Fugit::Cron.parse("*/1 * * * *").next_time(Time.find_zone!("Europe/Tallinn").parse("2012-10-28 02:59:00") + 1.minute).to_t
#=> 2012-10-28 03:01:00 +0300
Fugit::Cron.parse("*/1 * * * *").next_time(Time.find_zone!("Europe/Tallinn").parse("2012-10-28 03:59:00")).to_s
#=> "2012-10-28 03:00:00 +0200"
Issue description
According to https://www.timeanddate.com/time/change/estonia?year=2012 In Estonia, 2012 DST ended on October 28 after 03:59 (EEST) clock turned backward to 03:00 (EET). Some evidence confirming this when working with Time class:
But Fugit::Cron breaks on an attempt to calculate next time from cron
*/1 * * * *
starting from 03:00:00 EEST:How to reproduce
The simplest piece of code that reproduces the issue:
Error and error backtrace (if any)
Expected behaviour
Not get error thrown
Given:
Output:
2012-10-28 03:01:00 +0300
(+0300 signifies EEST)Given:
Output:
2012-10-28 03:00:00 +0200
(+0200 signifies EET)Context