rufus-scheduler 3.0.9 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2014, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2015, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2006-2014, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2006-2015, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -46,32 +46,9 @@ module Rufus
46
46
  o.is_a?(String) ? parse_duration(o, opts) : o
47
47
  end
48
48
 
49
- TZ_REGEX = /\b((?:[a-zA-Z][a-zA-z0-9\-+]+)(?:\/[a-zA-Z0-9_\-+]+)?)\b/
50
-
51
49
  def self.parse_at(o, opts={})
52
50
 
53
- return o if o.is_a?(Time)
54
-
55
- # TODO: deal with tz if suffixed to Chronic string?
56
- return Chronic.parse(o, opts) if defined?(Chronic)
57
-
58
- tz = nil
59
- s =
60
- o.to_s.gsub(TZ_REGEX) { |m|
61
- t = TZInfo::Timezone.get(m) rescue nil
62
- tz ||= t
63
- t ? '' : m
64
- }
65
-
66
- begin
67
- DateTime.parse(o)
68
- rescue
69
- raise ArgumentError, "no time information in #{o.inspect}"
70
- end if RUBY_VERSION < '1.9.0'
71
-
72
- t = Time.parse(s)
73
-
74
- tz ? tz.local_to_utc(t) : t
51
+ Rufus::Scheduler::ZoTime.parse(o, opts).time
75
52
 
76
53
  rescue StandardError => se
77
54
 
@@ -0,0 +1,174 @@
1
+ #--
2
+ # Copyright (c) 2006-2015, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+
26
+ class Rufus::Scheduler
27
+
28
+ TIMEZONES = %w[
29
+ GB NZ UCT EET CET PRC ROC WET GMT EST ROK UTC MST HST MET Zulu Cuba Iran W-SU
30
+ Eire GMT0 Libya Japan Egypt GMT+0 GMT-0 Israel Poland Navajo Turkey GB-Eire
31
+ Iceland PST8PDT Etc/UCT CST6CDT NZ-CHAT MST7MDT Jamaica EST5EDT Etc/GMT Etc/UTC
32
+ US/Samoa Etc/GMT0 Portugal Hongkong Etc/Zulu Singapore Asia/Baku Etc/GMT-9
33
+ Etc/GMT+1 Etc/GMT+0 Asia/Aden Etc/GMT+2 Etc/GMT+3 Etc/GMT+4 Etc/GMT+5 Etc/GMT+6
34
+ Etc/GMT+7 Etc/GMT+8 Etc/GMT+9 Etc/GMT-0 Etc/GMT-1 Universal Asia/Dili Greenwich
35
+ Asia/Gaza Etc/GMT-8 Etc/GMT-7 US/Alaska Asia/Oral Etc/GMT-6 Etc/GMT-5 Etc/GMT-4
36
+ Asia/Hovd Etc/GMT-3 US/Hawaii Etc/GMT-2 Kwajalein Asia/Omsk Asia/Macao
37
+ Etc/GMT-14 Asia/Kabul US/Central Etc/GMT-13 US/Arizona Asia/Macau Asia/Qatar
38
+ Asia/Seoul Asia/Tokyo Asia/Dubai US/Pacific Etc/GMT-12 Etc/GMT-11 Etc/GMT-10
39
+ Asia/Dhaka Asia/Dacca Asia/Chita Etc/GMT+12 Etc/GMT+10 Asia/Amman Asia/Aqtau
40
+ Etc/GMT+11 US/Eastern Asia/Thimbu Asia/Brunei Asia/Tehran Asia/Beirut
41
+ Europe/Rome Europe/Riga Brazil/Acre Brazil/East Europe/Oslo Brazil/West
42
+ Africa/Lome Asia/Taipei Asia/Saigon Asia/Riyadh Asia/Aqtobe Asia/Anadyr
43
+ Europe/Kiev Asia/Almaty Africa/Juba Pacific/Yap US/Aleutian Asia/Muscat
44
+ US/Mountain Asia/Harbin Asia/Hebron Asia/Manila Asia/Kuwait Asia/Urumqi
45
+ US/Michigan Indian/Mahe SystemV/EST5 Asia/Kashgar Indian/Cocos Asia/Jakarta
46
+ Asia/Kolkata Asia/Kuching America/Atka Asia/Irkutsk Pacific/Apia Asia/Magadan
47
+ Africa/Dakar America/Lima Pacific/Fiji Pacific/Guam Europe/Vaduz Pacific/Niue
48
+ Asia/Nicosia Africa/Ceuta Pacific/Truk America/Adak Pacific/Wake Africa/Tunis
49
+ Africa/Cairo Asia/Colombo SystemV/AST4 SystemV/CST6 Asia/Karachi Asia/Rangoon
50
+ SystemV/MST7 Asia/Baghdad Europe/Malta Africa/Lagos Europe/Minsk SystemV/PST8
51
+ Canada/Yukon Asia/Tbilisi America/Nome Asia/Bahrain Africa/Accra Europe/Paris
52
+ Asia/Bangkok Asia/Bishkek Asia/Thimphu SystemV/YST9 Asia/Yerevan Asia/Yakutsk
53
+ Europe/Sofia Asia/Ust-Nera Australia/ACT Australia/LHI Europe/Tirane
54
+ Asia/Tel_Aviv Australia/NSW Africa/Luanda Asia/Tashkent Africa/Lusaka
55
+ Asia/Shanghai Africa/Malabo Asia/Sakhalin Africa/Maputo Africa/Maseru
56
+ SystemV/HST10 Africa/Kigali Africa/Niamey Pacific/Samoa America/Sitka
57
+ Pacific/Palau Pacific/Nauru Pacific/Efate Asia/Makassar Pacific/Chuuk
58
+ Africa/Harare Africa/Douala America/Aruba America/Thule America/Bahia
59
+ America/Jujuy America/Belem Asia/Katmandu America/Boise Indian/Comoro
60
+ Indian/Chagos Asia/Jayapura Europe/Zurich Asia/Istanbul Europe/Zagreb
61
+ Etc/Greenwich Europe/Warsaw Europe/Vienna Etc/Universal Asia/Dushanbe
62
+ Europe/Athens Europe/Berlin Africa/Bissau Asia/Damascus Africa/Banjul
63
+ Europe/Dublin Africa/Bangui Africa/Bamako Europe/Jersey Africa/Asmera
64
+ Europe/Lisbon Africa/Asmara Europe/London Asia/Ashgabat Asia/Calcutta
65
+ Europe/Madrid Europe/Monaco Europe/Moscow Europe/Prague Europe/Samara
66
+ Europe/Skopje Asia/Khandyga Canada/Pacific Africa/Abidjan America/Manaus
67
+ Asia/Chongqing Asia/Chungking Africa/Algiers America/Maceio US/Pacific-New
68
+ Africa/Conakry America/La_Paz America/Juneau America/Nassau America/Inuvik
69
+ Europe/Andorra Africa/Kampala Asia/Ashkhabad Asia/Hong_Kong America/Havana
70
+ Canada/Eastern Europe/Belfast Canada/Central Australia/West Asia/Jerusalem
71
+ Africa/Mbabane Asia/Kamchatka America/Virgin America/Guyana Asia/Kathmandu
72
+ Mexico/General America/Panama Europe/Nicosia America/Denver Europe/Tallinn
73
+ Africa/Nairobi America/Dawson Europe/Vatican Europe/Vilnius America/Cuiaba
74
+ Africa/Tripoli Pacific/Wallis Atlantic/Faroe Pacific/Tarawa Pacific/Tahiti
75
+ Pacific/Saipan Pacific/Ponape America/Cayman America/Cancun Asia/Pontianak
76
+ Asia/Pyongyang Asia/Vientiane Asia/Qyzylorda Pacific/Noumea America/Bogota
77
+ Pacific/Midway Pacific/Majuro Asia/Samarkand Indian/Mayotte Pacific/Kosrae
78
+ Asia/Singapore Indian/Reunion America/Belize America/Regina America/Recife
79
+ Pacific/Easter Mexico/BajaSur America/Merida Pacific/Chatham Pacific/Fakaofo
80
+ Pacific/Gambier America/Rosario Asia/Ulan_Bator Indian/Maldives Pacific/Norfolk
81
+ America/Antigua Asia/Phnom_Penh America/Phoenix America/Caracas America/Cayenne
82
+ Atlantic/Azores Pacific/Pohnpei Atlantic/Canary America/Chicago Atlantic/Faeroe
83
+ Africa/Windhoek America/Cordoba America/Creston Africa/Timbuktu America/Curacao
84
+ Africa/Sao_Tome Africa/Ndjamena SystemV/AST4ADT Europe/Uzhgorod Europe/Tiraspol
85
+ SystemV/CST6CDT Africa/Monrovia America/Detroit Europe/Sarajevo Australia/Eucla
86
+ America/Tijuana America/Toronto America/Godthab America/Grenada Europe/Istanbul
87
+ America/Ojinaga America/Tortola Australia/Perth Europe/Helsinki Australia/South
88
+ Europe/Guernsey SystemV/EST5EDT Europe/Chisinau SystemV/MST7MDT Europe/Busingen
89
+ Europe/Budapest Europe/Brussels America/Halifax America/Mendoza America/Noronha
90
+ America/Nipigon Canada/Atlantic America/Yakutat SystemV/PST8PDT SystemV/YST9YDT
91
+ Canada/Mountain Africa/Kinshasa Africa/Khartoum Africa/Gaborone Africa/Freetown
92
+ America/Iqaluit America/Jamaica US/East-Indiana Africa/El_Aaiun America/Knox_IN
93
+ Africa/Djibouti Africa/Blantyre America/Moncton America/Managua Asia/Choibalsan
94
+ America/Marigot Australia/North Europe/Belgrade America/Resolute
95
+ America/Mazatlan Pacific/Funafuti Pacific/Auckland Pacific/Honolulu
96
+ Pacific/Johnston America/Miquelon America/Santarem Mexico/BajaNorte
97
+ America/Santiago Antarctica/Troll America/Asuncion America/Atikokan
98
+ America/Montreal America/Barbados Africa/Bujumbura Pacific/Pitcairn
99
+ Asia/Ulaanbaatar Indian/Mauritius America/New_York Antarctica/Syowa
100
+ America/Shiprock Indian/Kerguelen Asia/Novosibirsk America/Anguilla
101
+ Indian/Christmas Asia/Vladivostok Asia/Ho_Chi_Minh Antarctica/Davis
102
+ Atlantic/Bermuda Europe/Amsterdam Antarctica/Casey America/St_Johns
103
+ Atlantic/Madeira America/Winnipeg America/St_Kitts Europe/Volgograd
104
+ Brazil/DeNoronha Europe/Bucharest Africa/Mogadishu America/St_Lucia
105
+ Atlantic/Stanley Europe/Stockholm Australia/Currie Europe/Gibraltar
106
+ Australia/Sydney Asia/Krasnoyarsk Australia/Darwin America/Dominica
107
+ America/Edmonton America/Eirunepe Europe/Podgorica America/Ensenada
108
+ Europe/Ljubljana Australia/Hobart Europe/Mariehamn Africa/Lubumbashi
109
+ America/Goose_Bay Europe/Luxembourg America/Menominee America/Glace_Bay
110
+ America/Fortaleza Africa/Nouakchott America/Matamoros Pacific/Galapagos
111
+ America/Guatemala Pacific/Kwajalein Pacific/Marquesas America/Guayaquil
112
+ Asia/Kuala_Lumpur Europe/San_Marino America/Monterrey Europe/Simferopol
113
+ America/Araguaina Antarctica/Vostok Europe/Copenhagen America/Catamarca
114
+ Pacific/Pago_Pago America/Sao_Paulo America/Boa_Vista America/St_Thomas
115
+ Chile/Continental America/Vancouver Africa/Casablanca Europe/Bratislava
116
+ Pacific/Enderbury Pacific/Rarotonga Europe/Zaporozhye US/Indiana-Starke
117
+ Antarctica/Palmer Asia/Novokuznetsk Africa/Libreville America/Chihuahua
118
+ America/Anchorage Pacific/Tongatapu Antarctica/Mawson Africa/Porto-Novo
119
+ Asia/Yekaterinburg America/Paramaribo America/Hermosillo Atlantic/Jan_Mayen
120
+ Antarctica/McMurdo America/Costa_Rica Antarctica/Rothera America/Grand_Turk
121
+ Atlantic/Reykjavik Atlantic/St_Helena Australia/Victoria Chile/EasterIsland
122
+ Asia/Ujung_Pandang Australia/Adelaide America/Montserrat America/Porto_Acre
123
+ Africa/Brazzaville Australia/Brisbane America/Kralendijk America/Montevideo
124
+ America/St_Vincent America/Louisville Australia/Canberra Australia/Tasmania
125
+ Europe/Isle_of_Man Europe/Kaliningrad Africa/Ouagadougou America/Rio_Branco
126
+ Pacific/Kiritimati Africa/Addis_Ababa America/Metlakatla America/Martinique
127
+ Asia/Srednekolymsk America/Guadeloupe America/Fort_Wayne Australia/Lindeman
128
+ America/Whitehorse Arctic/Longyearbyen America/Pangnirtung America/Mexico_City
129
+ America/Los_Angeles America/Rainy_River Atlantic/Cape_Verde Pacific/Guadalcanal
130
+ Indian/Antananarivo America/El_Salvador Australia/Lord_Howe Africa/Johannesburg
131
+ America/Tegucigalpa Canada/Saskatchewan America/Thunder_Bay Canada/Newfoundland
132
+ America/Puerto_Rico America/Yellowknife Australia/Melbourne America/Porto_Velho
133
+ Australia/Queensland Australia/Yancowinna America/Santa_Isabel
134
+ America/Blanc-Sablon America/Scoresbysund America/Danmarkshavn
135
+ Pacific/Port_Moresby Antarctica/Macquarie America/Buenos_Aires
136
+ Africa/Dar_es_Salaam America/Campo_Grande America/Dawson_Creek
137
+ America/Indianapolis Pacific/Bougainville America/Rankin_Inlet
138
+ America/Indiana/Knox America/Lower_Princes America/Coral_Harbour
139
+ America/St_Barthelemy Australia/Broken_Hill America/Cambridge_Bay
140
+ America/Indiana/Vevay America/Swift_Current America/Port_of_Spain
141
+ Antarctica/South_Pole America/Santo_Domingo Atlantic/South_Georgia
142
+ America/Port-au-Prince America/Bahia_Banderas America/Indiana/Winamac
143
+ America/Indiana/Marengo America/Argentina/Jujuy America/Argentina/Salta
144
+ Canada/East-Saskatchewan America/Indiana/Vincennes America/Argentina/Tucuman
145
+ America/Argentina/Ushuaia Antarctica/DumontDUrville America/Indiana/Tell_City
146
+ America/Argentina/Mendoza America/Argentina/Cordoba America/Indiana/Petersburg
147
+ America/Argentina/San_Luis America/Argentina/San_Juan America/Argentina/La_Rioja
148
+ America/North_Dakota/Center America/Kentucky/Monticello
149
+ America/North_Dakota/Beulah America/Kentucky/Louisville
150
+ America/Argentina/Catamarca America/Indiana/Indianapolis
151
+ America/North_Dakota/New_Salem America/Argentina/Rio_Gallegos
152
+ America/Argentina/Buenos_Aires America/Argentina/ComodRivadavia
153
+ ]
154
+
155
+ ##
156
+ ## http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
157
+ #
158
+ #ABBREVIATIONS = %w[
159
+ #ACDT ACST ACT ADT AEDT AEST AFT AKDT AKST AMST AMST AMT AMT ART AST AST AWDT
160
+ #AWST AZOST AZT BDT BIOT BIT BOT BRT BST BST BTT CAT CCT CDT CDT CEDT CEST CET
161
+ #CHADT CHAST CHOT ChST CHUT CIST CIT CKT CLST CLT COST COT CST CST CST CST CST
162
+ #CT CVT CWST CXT DAVT DDUT DFT EASST EAST EAT ECT ECT EDT EEDT EEST EET EGST EGT
163
+ #EIT EST EST FET FJT FKST FKST FKT FNT GALT GAMT GET GFT GILT GIT GMT GST GST
164
+ #GYT HADT HAEC HAST HKT HMT HOVT HST ICT IDT IOT IRDT IRKT IRST IST IST IST JST
165
+ #KGT KOST KRAT KST LHST LHST LINT MAGT MART MAWT MDT MET MEST MHT MIST MIT MMT
166
+ #MSK MST MST MST MUT MVT MYT NCT NDT NFT NPT NST NT NUT NZDT NZST OMST ORAT PDT
167
+ #PET PETT PGT PHOT PKT PMDT PMST PONT PST PST PYST PYT RET ROTT SAKT SAMT SAST
168
+ #SBT SCT SGT SLST SRET SRT SST SST SYOT TAHT THA TFT TJT TKT TLT TMT TOT TVT UCT
169
+ #ULAT USZ1 UTC UYST UYT UZT VET VLAT VOLT VOST VUT WAKT WAST WAT WEDT WEST WET
170
+ #WIT WST YAKT YEKT Z
171
+ #].uniq
172
+
173
+ end
174
+
@@ -0,0 +1,154 @@
1
+ #--
2
+ # Copyright (c) 2006-2015, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+ require 'rufus/scheduler/zones'
26
+
27
+
28
+ class Rufus::Scheduler
29
+
30
+ #
31
+ # Zon{ing|ed}Time, whatever.
32
+ #
33
+ class ZoTime
34
+
35
+ attr_accessor :seconds
36
+ attr_accessor :zone
37
+
38
+ def initialize(s, zone)
39
+
40
+ @seconds = s.to_f
41
+ @zone = zone
42
+ end
43
+
44
+ def time
45
+
46
+ in_zone do
47
+
48
+ t = Time.at(@seconds)
49
+
50
+ if t.isdst
51
+ t1 = Time.at(@seconds + 3600)
52
+ t = t1 if t.zone != t1.zone && t.hour == t1.hour && t.min == t1.min
53
+ # ambiguous TZ (getting out of DST)
54
+ else
55
+ t.hour # force t to compute itself
56
+ end
57
+
58
+ t
59
+ end
60
+ end
61
+
62
+ def utc
63
+
64
+ time.utc
65
+ end
66
+
67
+ def add(s)
68
+
69
+ @seconds += s.to_f
70
+ end
71
+
72
+ def substract(s)
73
+
74
+ @seconds -= s.to_f
75
+ end
76
+
77
+ def to_f
78
+
79
+ @seconds
80
+ end
81
+
82
+ #DELTA_TZ_REX = /^[+-][0-1][0-9]:?[0-5][0-9]$/
83
+
84
+ def self.envtzable?(s)
85
+
86
+ TIMEZONES.include?(s)
87
+ end
88
+
89
+ def self.parse(str, opts={})
90
+
91
+ if defined?(::Chronic) && t = ::Chronic.parse(str, opts)
92
+ return ZoTime.new(t, ENV['TZ'])
93
+ end
94
+
95
+ begin
96
+ DateTime.parse(str)
97
+ rescue
98
+ raise ArgumentError, "no time information in #{o.inspect}"
99
+ end if RUBY_VERSION < '1.9.0'
100
+
101
+ zone = nil
102
+
103
+ s =
104
+ str.gsub(/\S+/) { |m|
105
+ if envtzable?(m)
106
+ zone ||= m
107
+ ''
108
+ else
109
+ m
110
+ end
111
+ }
112
+
113
+ return nil unless zone.nil? || is_timezone?(zone)
114
+
115
+ zt = ZoTime.new(0, zone || ENV['TZ'])
116
+ zt.in_zone { zt.seconds = Time.parse(s).to_f }
117
+
118
+ zt.seconds == nil ? nil : zt
119
+ end
120
+
121
+ def self.is_timezone?(str)
122
+
123
+ return false if str == nil
124
+
125
+ return true if Time.zone_offset(str)
126
+ return true if str == 'Zulu'
127
+
128
+ return !! (::TZInfo::Timezone.get(str) rescue nil) if defined?(::TZInfo)
129
+
130
+ zt = ZoTime.new(0, str)
131
+ t = zt.time
132
+
133
+ return false if t.zone == ''
134
+ return false if str.match(/[a-z]/) && str.start_with?(t.zone)
135
+
136
+ return false if RUBY_PLATFORM.include?('java') && ! envtzable?(str)
137
+
138
+ true
139
+ end
140
+
141
+ def in_zone(&block)
142
+
143
+ current_timezone = ENV['TZ']
144
+ ENV['TZ'] = @zone
145
+
146
+ block.call
147
+
148
+ ensure
149
+
150
+ ENV['TZ'] = current_timezone
151
+ end
152
+ end
153
+ end
154
+
@@ -26,38 +26,13 @@ job scheduler for Ruby (at, cron, in and every jobs).
26
26
  '*.gemspec', '*.txt', '*.rdoc', '*.md'
27
27
  ]
28
28
 
29
- s.add_runtime_dependency 'tzinfo'
29
+ #s.add_runtime_dependency 'tzinfo'
30
30
 
31
31
  s.add_development_dependency 'rake'
32
32
  s.add_development_dependency 'rspec', '>= 2.13.0'
33
33
  s.add_development_dependency 'chronic'
34
+ s.add_development_dependency 'tzinfo'
34
35
 
35
36
  s.require_path = 'lib'
36
-
37
- s.post_install_message =
38
- %{
39
- ***
40
-
41
- Thanks for installing rufus-scheduler #{s.version}
42
-
43
- It might not be 100% compatible with rufus-scheduler 2.x.
44
-
45
- If you encounter issues with this new rufus-scheduler, especially
46
- if your app worked fine with previous versions of it, you can
47
-
48
- A) Forget it and peg your Gemfile to rufus-scheduler 2.0.24
49
-
50
- and / or
51
-
52
- B) Take some time to carefully report the issue at
53
- https://github.com/jmettraux/rufus-scheduler/issues
54
-
55
- For general help about rufus-scheduler, ask via:
56
- http://stackoverflow.com/questions/ask?tags=rufus-scheduler+ruby
57
-
58
- Cheers.
59
-
60
- ***
61
- }
62
37
  end
63
38
 
@@ -5,7 +5,6 @@
5
5
  # Sat Mar 21 12:55:27 JST 2009
6
6
  #
7
7
 
8
- require 'tzinfo'
9
8
  require 'spec_helper'
10
9
 
11
10
 
@@ -15,6 +14,24 @@ describe Rufus::Scheduler::CronLine do
15
14
  Rufus::Scheduler::CronLine.new(cronline_string)
16
15
  end
17
16
 
17
+ def nt(cronline, now)
18
+ Rufus::Scheduler::CronLine.new(cronline).next_time(now)
19
+ end
20
+ def ntz(cronline, now)
21
+ tz = cronline.split.last
22
+ tu = nt(cronline, now).utc
23
+ in_zone(tz) { tu.getlocal }
24
+ end
25
+
26
+ def pt(cronline, now)
27
+ Rufus::Scheduler::CronLine.new(cronline).previous_time(now)
28
+ end
29
+ def ptz(cronline, now)
30
+ tz = cronline.split.last
31
+ tu = pt(cronline, now).utc
32
+ in_zone(tz) { tu.getlocal }
33
+ end
34
+
18
35
  def match(line, time)
19
36
  expect(cl(line).matches?(time)).to eq(true)
20
37
  end
@@ -49,12 +66,20 @@ describe Rufus::Scheduler::CronLine do
49
66
 
50
67
  to_a '0 0 1 1 *', [ [0], [0], [0], [1], [1], nil, nil, nil ]
51
68
 
52
- to_a '0 23-24 * * *', [ [0], [0], [23, 0], nil, nil, nil, nil, nil ]
69
+ if ruby18?
70
+ to_a '0 23-24 * * *', [ [0], [0], [0, 23], nil, nil, nil, nil, nil ]
71
+ else
72
+ to_a '0 23-24 * * *', [ [0], [0], [23, 0], nil, nil, nil, nil, nil ]
73
+ end
53
74
  #
54
75
  # as reported by Aimee Rose in
55
76
  # https://github.com/jmettraux/rufus-scheduler/issues/56
56
77
 
57
- to_a '0 23-2 * * *', [ [0], [0], [23, 0, 1, 2], nil, nil, nil, nil, nil ]
78
+ if ruby18?
79
+ to_a '0 23-2 * * *', [ [0], [0], [0, 1, 2, 23], nil, nil, nil, nil, nil ]
80
+ else
81
+ to_a '0 23-2 * * *', [ [0], [0], [23, 0, 1, 2], nil, nil, nil, nil, nil ]
82
+ end
58
83
  end
59
84
 
60
85
  it 'rejects invalid weekday expressions' do
@@ -92,7 +117,10 @@ describe Rufus::Scheduler::CronLine do
92
117
 
93
118
  to_a(
94
119
  '0 */2 * * *',
95
- [ [0], [0], (0..11).collect { |e| e * 2 }, nil, nil, nil, nil, nil ])
120
+ [ [0], [0], (0..23).select { |e| e.even? }, nil, nil, nil, nil, nil ])
121
+ to_a(
122
+ '0 0-23/2 * * *',
123
+ [ [0], [0], (0..23).select { |e| e.even? }, nil, nil, nil, nil, nil ])
96
124
  to_a(
97
125
  '0 7-23/2 * * *',
98
126
  [ [0], [0], (7..23).select { |e| e.odd? }, nil, nil, nil, nil, nil ])
@@ -189,56 +217,34 @@ describe Rufus::Scheduler::CronLine do
189
217
 
190
218
  describe '#next_time' do
191
219
 
192
- def nt(cronline, now)
193
- Rufus::Scheduler::CronLine.new(cronline).next_time(now)
194
- end
195
- def ntz(cronline, now)
196
- tz = cronline.split.last
197
- tu = nt(cronline, now).utc
198
- in_zone(tz) { tu.getlocal }
199
- end
200
-
201
220
  it 'computes the next occurence correctly' do
202
221
 
203
- now = Time.at(0).getutc # Thu Jan 01 00:00:00 UTC 1970
204
-
205
- expect(nt('* * * * *', now)).to eq(now + 60)
206
- expect(nt('* * * * sun', now)).to eq(now + 259200)
207
- expect(nt('* * * * * *', now)).to eq(now + 1)
208
- expect(nt('* * 13 * fri', now)).to eq(now + 3715200)
209
-
210
- expect(nt('10 12 13 12 *', now)).to eq(now + 29938200)
211
- # this one is slow (1 year == 3 seconds)
212
- #
213
- # historical note:
214
- # (comment made in 2006 or 2007, the underlying libs got better and
215
- # that slowness is gone)
216
-
217
- expect(nt('0 0 * * thu', now)).to eq(now + 604800)
218
- expect(nt('00 0 * * thu', now)).to eq(now + 604800)
222
+ in_zone 'Europe/Berlin' do
219
223
 
220
- expect(nt('0 0 * * *', now)).to eq(now + 24 * 3600)
221
- expect(nt('0 24 * * *', now)).to eq(now + 24 * 3600)
224
+ now = Time.at(0) - 3600
222
225
 
223
- now = local(2008, 12, 31, 23, 59, 59, 0)
226
+ expect(nt('* * * * *', now)).to eq(now + 60)
227
+ expect(nt('* * * * sun', now)).to eq(now + 259200)
228
+ expect(nt('* * * * * *', now)).to eq(now + 1)
229
+ expect(nt('* * 13 * fri', now)).to eq(now + 3715200)
224
230
 
225
- expect(nt('* * * * *', now)).to eq(now + 1)
226
- end
231
+ expect(nt('10 12 13 12 *', now)).to eq(now + 29938200)
232
+ # this one is slow (1 year == 3 seconds)
233
+ #
234
+ # historical note:
235
+ # (comment made in 2006 or 2007, the underlying libs got better and
236
+ # that slowness is gone)
227
237
 
228
- it 'computes the next occurence correctly in UTC (TZ not specified)' do
238
+ expect(nt('0 0 * * thu', now)).to eq(now + 604800)
239
+ expect(nt('00 0 * * thu', now)).to eq(now + 604800)
229
240
 
230
- now = utc(1970, 1, 1)
241
+ expect(nt('0 0 * * *', now)).to eq(now + 24 * 3600)
242
+ expect(nt('0 24 * * *', now)).to eq(now + 24 * 3600)
231
243
 
232
- expect(nt('* * * * *', now)).to eq(utc(1970, 1, 1, 0, 1))
233
- expect(nt('* * * * sun', now)).to eq(utc(1970, 1, 4))
234
- expect(nt('* * * * * *', now)).to eq(utc(1970, 1, 1, 0, 0, 1))
235
- expect(nt('* * 13 * fri', now)).to eq(utc(1970, 2, 13))
236
-
237
- expect(nt('10 12 13 12 *', now)).to eq(utc(1970, 12, 13, 12, 10))
238
- # this one is slow (1 year == 3 seconds)
239
- expect(nt('* * 1 6 *', now)).to eq(utc(1970, 6, 1))
244
+ now = local(2008, 12, 31, 23, 59, 59, 0)
240
245
 
241
- expect(nt('0 0 * * thu', now)).to eq(utc(1970, 1, 8))
246
+ expect(nt('* * * * *', now)).to eq(now + 1)
247
+ end
242
248
  end
243
249
 
244
250
  it 'computes the next occurence correctly in local TZ (TZ not specified)' do
@@ -260,9 +266,7 @@ describe Rufus::Scheduler::CronLine do
260
266
  it 'computes the next occurence correctly in UTC (TZ specified)' do
261
267
 
262
268
  zone = 'Europe/Stockholm'
263
- tz = TZInfo::Timezone.get(zone)
264
- now = tz.local_to_utc(local(1970, 1, 1))
265
- # Midnight in zone, UTC
269
+ now = in_zone(zone) { Time.local(1970, 1, 1) }
266
270
 
267
271
  expect(nt("* * * * * #{zone}", now)).to eq(utc(1969, 12, 31, 23, 1))
268
272
  expect(nt("* * * * sun #{zone}", now)).to eq(utc(1970, 1, 3, 23))
@@ -275,20 +279,6 @@ describe Rufus::Scheduler::CronLine do
275
279
  expect(nt("0 0 * * thu #{zone}", now)).to eq(utc(1970, 1, 7, 23))
276
280
  end
277
281
 
278
- #it 'computes the next occurence correctly in local TZ (TZ specified)' do
279
- # zone = 'Europe/Stockholm'
280
- # tz = TZInfo::Timezone.get(zone)
281
- # now = tz.local_to_utc(utc(1970, 1, 1)).localtime
282
- # # Midnight in zone, local time
283
- # nt("* * * * * #{zone}", now).should == local(1969, 12, 31, 18, 1)
284
- # nt("* * * * sun #{zone}", now).should == local(1970, 1, 3, 18)
285
- # nt("* * * * * * #{zone}", now).should == local(1969, 12, 31, 18, 0, 1)
286
- # nt("* * 13 * fri #{zone}", now).should == local(1970, 2, 12, 18)
287
- # nt("10 12 13 12 * #{zone}", now).should == local(1970, 12, 13, 6, 10)
288
- # nt("* * 1 6 * #{zone}", now).should == local(1970, 5, 31, 19)
289
- # nt("0 0 * * thu #{zone}", now).should == local(1970, 1, 7, 18)
290
- #end
291
-
292
282
  it 'computes the next time correctly when there is a sun#2 involved' do
293
283
 
294
284
  expect(nt('* * * * sun#1', local(1970, 1, 1))).to eq(local(1970, 1, 4))
@@ -375,15 +365,6 @@ describe Rufus::Scheduler::CronLine do
375
365
 
376
366
  describe '#previous_time' do
377
367
 
378
- def pt(cronline, now)
379
- Rufus::Scheduler::CronLine.new(cronline).previous_time(now)
380
- end
381
- def ptz(cronline, now)
382
- tz = cronline.split.last
383
- tu = pt(cronline, now).utc
384
- in_zone(tz) { tu.getlocal }
385
- end
386
-
387
368
  it 'returns the previous time the cron should have triggered' do
388
369
 
389
370
  expect(
@@ -438,21 +419,21 @@ describe Rufus::Scheduler::CronLine do
438
419
 
439
420
  describe '#matches?' do
440
421
 
441
- it 'matches correctly in UTC (TZ not specified)' do
442
-
443
- match '* * * * *', utc(1970, 1, 1, 0, 1)
444
- match '* * * * sun', utc(1970, 1, 4)
445
- match '* * * * * *', utc(1970, 1, 1, 0, 0, 1)
446
- match '* * 13 * fri', utc(1970, 2, 13)
447
-
448
- match '10 12 13 12 *', utc(1970, 12, 13, 12, 10)
449
- match '* * 1 6 *', utc(1970, 6, 1)
450
-
451
- match '0 0 * * thu', utc(1970, 1, 8)
452
-
453
- match '0 0 1 1 *', utc(2012, 1, 1)
454
- no_match '0 0 1 1 *', utc(2012, 1, 1, 1, 0)
455
- end
422
+ # it 'matches correctly in UTC (TZ not specified)' do
423
+ #
424
+ # match '* * * * *', utc(1970, 1, 1, 0, 1)
425
+ # match '* * * * sun', utc(1970, 1, 4)
426
+ # match '* * * * * *', utc(1970, 1, 1, 0, 0, 1)
427
+ # match '* * 13 * fri', utc(1970, 2, 13)
428
+ #
429
+ # match '10 12 13 12 *', utc(1970, 12, 13, 12, 10)
430
+ # match '* * 1 6 *', utc(1970, 6, 1)
431
+ #
432
+ # match '0 0 * * thu', utc(1970, 1, 8)
433
+ #
434
+ # match '0 0 1 1 *', utc(2012, 1, 1)
435
+ # no_match '0 0 1 1 *', utc(2012, 1, 1, 1, 0)
436
+ # end
456
437
 
457
438
  it 'matches correctly in local TZ (TZ not specified)' do
458
439
 
@@ -546,19 +527,19 @@ describe Rufus::Scheduler::CronLine do
546
527
  it 'returns the shortest delta between two occurrences' do
547
528
 
548
529
  expect(Rufus::Scheduler::CronLine.new(
549
- '* * * * *').frequency).to eq(60)
530
+ '* * * * *').frequency).to eq(60)
550
531
  expect(Rufus::Scheduler::CronLine.new(
551
- '* * * * * *').frequency).to eq(1)
532
+ '* * * * * *').frequency).to eq(1)
552
533
 
553
534
  expect(Rufus::Scheduler::CronLine.new(
554
- '5 23 * * *').frequency).to eq(24 * 3600)
535
+ '5 23 * * *').frequency).to eq(24 * 3600)
555
536
  expect(Rufus::Scheduler::CronLine.new(
556
- '5 * * * *').frequency).to eq(3600)
537
+ '5 * * * *').frequency).to eq(3600)
557
538
  expect(Rufus::Scheduler::CronLine.new(
558
- '10,20,30 * * * *').frequency).to eq(600)
539
+ '10,20,30 * * * *').frequency).to eq(600)
559
540
 
560
541
  expect(Rufus::Scheduler::CronLine.new(
561
- '10,20,30 * * * * *').frequency).to eq(10)
542
+ '10,20,30 * * * * *').frequency).to eq(10)
562
543
  end
563
544
  end
564
545
 
@@ -567,22 +548,30 @@ describe Rufus::Scheduler::CronLine do
567
548
  it 'returns the shortest delta between two occurrences' do
568
549
 
569
550
  expect(Rufus::Scheduler::CronLine.new(
570
- '* * * * *').brute_frequency).to eq(60)
551
+ '* * * * *').brute_frequency).to eq(60)
571
552
  expect(Rufus::Scheduler::CronLine.new(
572
- '* * * * * *').brute_frequency).to eq(1)
553
+ '* * * * * *').brute_frequency).to eq(1)
573
554
 
574
555
  expect(Rufus::Scheduler::CronLine.new(
575
- '5 23 * * *').brute_frequency).to eq(24 * 3600)
556
+ '5 23 * * *').brute_frequency).to eq(24 * 3600)
576
557
  expect(Rufus::Scheduler::CronLine.new(
577
- '5 * * * *').brute_frequency).to eq(3600)
558
+ '5 * * * *').brute_frequency).to eq(3600)
578
559
  expect(Rufus::Scheduler::CronLine.new(
579
- '10,20,30 * * * *').brute_frequency).to eq(600)
560
+ '10,20,30 * * * *').brute_frequency).to eq(600)
580
561
 
581
562
  #Rufus::Scheduler::CronLine.new(
582
563
  # '10,20,30 * * * * *').brute_frequency.should == 10
583
564
  #
584
565
  # takes > 20s ...
585
566
  end
567
+
568
+ # some combos only appear every other year...
569
+ #
570
+ it 'does not go into an infinite loop' do
571
+
572
+ expect(Rufus::Scheduler::CronLine.new(
573
+ '1 2 3 4 5').brute_frequency).to eq(31622400)
574
+ end
586
575
  end
587
576
 
588
577
  context 'summer time' do
@@ -593,10 +582,6 @@ describe Rufus::Scheduler::CronLine do
593
582
  #
594
583
  it 'schedules correctly through a switch into summer time' do
595
584
 
596
- #j = `zdump -v Europe/Berlin | grep "Sun Mar" | grep 2014`.split("\n")[0]
597
- #j = j.match(/^.+ (Sun Mar .+ UTC) /)[1]
598
- # only works on system that have a zdump...
599
-
600
585
  in_zone 'Europe/Berlin' do
601
586
 
602
587
  # find the summer jump
@@ -623,14 +608,14 @@ describe Rufus::Scheduler::CronLine do
623
608
  n0 = cl0.next_time(friday)
624
609
  n1 = cl1.next_time(friday)
625
610
 
626
- expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 MON')
611
+ expect(n0.strftime('%H:%M:%S %^a')).to eq('00:02:00 TUE')
627
612
  expect(n1.strftime('%H:%M:%S %^a')).to eq('08:45:00 MON')
628
613
 
629
614
  expect(n0.isdst).to eq(true)
630
615
  expect(n1.isdst).to eq(true)
631
616
 
632
617
  expect(
633
- (n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('23:02:00 THU')
618
+ (n0 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('23:02:00 FRI')
634
619
  expect(
635
620
  (n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('07:45:00 FRI')
636
621
  end
@@ -676,6 +661,70 @@ describe Rufus::Scheduler::CronLine do
676
661
  (n1 - 24 * 3600 * 3).strftime('%H:%M:%S %^a')).to eq('09:45:00 FRI')
677
662
  end
678
663
  end
664
+
665
+ it 'correctly increments through a DST transition' do
666
+
667
+ expect(
668
+ nt('* * * * * America/Los_Angeles', Time.utc(2015, 3, 8, 9, 59))
669
+ ).to eq(Time.utc(2015, 3, 8, 10, 00))
670
+ end
671
+
672
+ it 'correctly increments every minute through a DST transition' do
673
+
674
+ in_zone 'America/Los_Angeles' do
675
+
676
+ line = cl('* * * * * America/Los_Angeles')
677
+
678
+ t = Time.local(2015, 3, 8, 1, 57)
679
+
680
+ points =
681
+ [ 0, 1, 2, 3 ].collect do
682
+ t = line.next_time(t)
683
+ t.strftime('%H:%M:%Sl') + ' ' + t.dup.utc.strftime('%H:%M:%Su')
684
+ end
685
+
686
+ expect(points).to eq(
687
+ [
688
+ '01:58:00l 09:58:00u',
689
+ '01:59:00l 09:59:00u',
690
+ '03:00:00l 10:00:00u',
691
+ '03:01:00l 10:01:00u'
692
+ ]
693
+ )
694
+ end
695
+ end
696
+
697
+ it 'correctly decrements through a DST transition' do
698
+
699
+ expect(
700
+ pt('* * * * * America/Los_Angeles', Time.utc(2015, 3, 8, 10, 00))
701
+ ).to eq(Time.utc(2015, 3, 8, 9, 59))
702
+ end
703
+
704
+ it 'correctly decrements every minute through a DST transition' do
705
+
706
+ in_zone 'America/Los_Angeles' do
707
+
708
+ line = cl('* * * * * America/Los_Angeles')
709
+
710
+ t = Time.local(2015, 3, 8, 3, 2)
711
+
712
+ points =
713
+ [ 0, 1, 2, 3 ].collect do
714
+ t = line.previous_time(t)
715
+ t.strftime('%H:%M:%Sl') + ' ' + t.dup.utc.strftime('%H:%M:%Su')
716
+ end
717
+
718
+ expect(points).to eq(
719
+ [
720
+ '03:01:00l 10:01:00u',
721
+ '03:00:00l 10:00:00u',
722
+ '01:59:00l 09:59:00u',
723
+ '01:58:00l 09:58:00u'
724
+ ]
725
+ )
726
+ end
727
+ end
679
728
  end
680
729
  end
681
730