tzinfo 1.2.11 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.yardopts +3 -0
- data/CHANGES.md +469 -431
- data/LICENSE +13 -13
- data/README.md +368 -114
- data/lib/tzinfo/country.rb +131 -129
- data/lib/tzinfo/country_timezone.rb +70 -112
- data/lib/tzinfo/data_source.rb +389 -144
- data/lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb +56 -0
- data/lib/tzinfo/data_sources/country_info.rb +42 -0
- data/lib/tzinfo/data_sources/data_timezone_info.rb +91 -0
- data/lib/tzinfo/data_sources/linked_timezone_info.rb +33 -0
- data/lib/tzinfo/data_sources/ruby_data_source.rb +141 -0
- data/lib/tzinfo/data_sources/timezone_info.rb +47 -0
- data/lib/tzinfo/data_sources/transitions_data_timezone_info.rb +214 -0
- data/lib/tzinfo/data_sources/zoneinfo_data_source.rb +573 -0
- data/lib/tzinfo/data_sources/zoneinfo_reader.rb +284 -0
- data/lib/tzinfo/data_sources.rb +8 -0
- data/lib/tzinfo/data_timezone.rb +33 -47
- data/lib/tzinfo/datetime_with_offset.rb +153 -0
- data/lib/tzinfo/format1/country_definer.rb +17 -0
- data/lib/tzinfo/format1/country_index_definition.rb +64 -0
- data/lib/tzinfo/format1/timezone_definer.rb +64 -0
- data/lib/tzinfo/format1/timezone_definition.rb +39 -0
- data/lib/tzinfo/format1/timezone_index_definition.rb +77 -0
- data/lib/tzinfo/format1.rb +10 -0
- data/lib/tzinfo/format2/country_definer.rb +68 -0
- data/lib/tzinfo/format2/country_index_definer.rb +68 -0
- data/lib/tzinfo/format2/country_index_definition.rb +46 -0
- data/lib/tzinfo/format2/timezone_definer.rb +94 -0
- data/lib/tzinfo/format2/timezone_definition.rb +73 -0
- data/lib/tzinfo/format2/timezone_index_definer.rb +45 -0
- data/lib/tzinfo/format2/timezone_index_definition.rb +55 -0
- data/lib/tzinfo/format2.rb +10 -0
- data/lib/tzinfo/info_timezone.rb +26 -21
- data/lib/tzinfo/linked_timezone.rb +33 -52
- data/lib/tzinfo/offset_timezone_period.rb +42 -0
- data/lib/tzinfo/string_deduper.rb +118 -0
- data/lib/tzinfo/time_with_offset.rb +128 -0
- data/lib/tzinfo/timestamp.rb +548 -0
- data/lib/tzinfo/timestamp_with_offset.rb +85 -0
- data/lib/tzinfo/timezone.rb +979 -502
- data/lib/tzinfo/timezone_offset.rb +84 -74
- data/lib/tzinfo/timezone_period.rb +151 -217
- data/lib/tzinfo/timezone_proxy.rb +70 -79
- data/lib/tzinfo/timezone_transition.rb +77 -109
- data/lib/tzinfo/transitions_timezone_period.rb +63 -0
- data/lib/tzinfo/version.rb +7 -0
- data/lib/tzinfo/with_offset.rb +61 -0
- data/lib/tzinfo.rb +60 -40
- data.tar.gz.sig +0 -0
- metadata +51 -115
- metadata.gz.sig +2 -3
- data/Rakefile +0 -107
- data/lib/tzinfo/annual_rules.rb +0 -51
- data/lib/tzinfo/country_index_definition.rb +0 -31
- data/lib/tzinfo/country_info.rb +0 -42
- data/lib/tzinfo/data_timezone_info.rb +0 -55
- data/lib/tzinfo/linked_timezone_info.rb +0 -26
- data/lib/tzinfo/offset_rationals.rb +0 -77
- data/lib/tzinfo/posix_time_zone_parser.rb +0 -136
- data/lib/tzinfo/ruby_core_support.rb +0 -176
- data/lib/tzinfo/ruby_country_info.rb +0 -74
- data/lib/tzinfo/ruby_data_source.rb +0 -136
- data/lib/tzinfo/time_or_datetime.rb +0 -351
- data/lib/tzinfo/timezone_definition.rb +0 -36
- data/lib/tzinfo/timezone_index_definition.rb +0 -54
- data/lib/tzinfo/timezone_info.rb +0 -30
- data/lib/tzinfo/timezone_transition_definition.rb +0 -104
- data/lib/tzinfo/transition_data_timezone_info.rb +0 -274
- data/lib/tzinfo/transition_rule.rb +0 -325
- data/lib/tzinfo/zoneinfo_country_info.rb +0 -37
- data/lib/tzinfo/zoneinfo_data_source.rb +0 -504
- data/lib/tzinfo/zoneinfo_timezone_info.rb +0 -516
- data/test/assets/payload.rb +0 -1
- data/test/tc_annual_rules.rb +0 -95
- data/test/tc_country.rb +0 -240
- data/test/tc_country_index_definition.rb +0 -69
- data/test/tc_country_info.rb +0 -16
- data/test/tc_country_timezone.rb +0 -173
- data/test/tc_data_source.rb +0 -218
- data/test/tc_data_timezone.rb +0 -99
- data/test/tc_data_timezone_info.rb +0 -18
- data/test/tc_info_timezone.rb +0 -34
- data/test/tc_linked_timezone.rb +0 -155
- data/test/tc_linked_timezone_info.rb +0 -23
- data/test/tc_offset_rationals.rb +0 -23
- data/test/tc_posix_time_zone_parser.rb +0 -261
- data/test/tc_ruby_core_support.rb +0 -168
- data/test/tc_ruby_country_info.rb +0 -110
- data/test/tc_ruby_data_source.rb +0 -175
- data/test/tc_time_or_datetime.rb +0 -674
- data/test/tc_timezone.rb +0 -1361
- data/test/tc_timezone_definition.rb +0 -113
- data/test/tc_timezone_index_definition.rb +0 -73
- data/test/tc_timezone_info.rb +0 -11
- data/test/tc_timezone_london.rb +0 -143
- data/test/tc_timezone_melbourne.rb +0 -142
- data/test/tc_timezone_new_york.rb +0 -142
- data/test/tc_timezone_offset.rb +0 -126
- data/test/tc_timezone_period.rb +0 -555
- data/test/tc_timezone_proxy.rb +0 -136
- data/test/tc_timezone_transition.rb +0 -366
- data/test/tc_timezone_transition_definition.rb +0 -295
- data/test/tc_timezone_utc.rb +0 -27
- data/test/tc_transition_data_timezone_info.rb +0 -433
- data/test/tc_transition_rule.rb +0 -663
- data/test/tc_zoneinfo_country_info.rb +0 -78
- data/test/tc_zoneinfo_data_source.rb +0 -1226
- data/test/tc_zoneinfo_timezone_info.rb +0 -2149
- data/test/test_utils.rb +0 -214
- data/test/ts_all.rb +0 -7
- data/test/ts_all_ruby.rb +0 -5
- data/test/ts_all_zoneinfo.rb +0 -9
- data/test/tzinfo-data/tzinfo/data/definitions/America/Argentina/Buenos_Aires.rb +0 -89
- data/test/tzinfo-data/tzinfo/data/definitions/America/New_York.rb +0 -327
- data/test/tzinfo-data/tzinfo/data/definitions/Australia/Melbourne.rb +0 -230
- data/test/tzinfo-data/tzinfo/data/definitions/EST.rb +0 -19
- data/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__m__1.rb +0 -21
- data/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__p__1.rb +0 -21
- data/test/tzinfo-data/tzinfo/data/definitions/Etc/UTC.rb +0 -21
- data/test/tzinfo-data/tzinfo/data/definitions/Europe/Amsterdam.rb +0 -273
- data/test/tzinfo-data/tzinfo/data/definitions/Europe/Andorra.rb +0 -198
- data/test/tzinfo-data/tzinfo/data/definitions/Europe/London.rb +0 -333
- data/test/tzinfo-data/tzinfo/data/definitions/Europe/Paris.rb +0 -277
- data/test/tzinfo-data/tzinfo/data/definitions/Europe/Prague.rb +0 -235
- data/test/tzinfo-data/tzinfo/data/definitions/UTC.rb +0 -16
- data/test/tzinfo-data/tzinfo/data/indexes/countries.rb +0 -940
- data/test/tzinfo-data/tzinfo/data/indexes/timezones.rb +0 -609
- data/test/tzinfo-data/tzinfo/data/version.rb +0 -20
- data/test/tzinfo-data/tzinfo/data.rb +0 -8
- data/test/zoneinfo/America/Argentina/Buenos_Aires +0 -0
- data/test/zoneinfo/America/New_York +0 -0
- data/test/zoneinfo/Australia/Melbourne +0 -0
- data/test/zoneinfo/EST +0 -0
- data/test/zoneinfo/Etc/UTC +0 -0
- data/test/zoneinfo/Europe/Amsterdam +0 -0
- data/test/zoneinfo/Europe/Andorra +0 -0
- data/test/zoneinfo/Europe/London +0 -0
- data/test/zoneinfo/Europe/Paris +0 -0
- data/test/zoneinfo/Europe/Prague +0 -0
- data/test/zoneinfo/Factory +0 -0
- data/test/zoneinfo/iso3166.tab +0 -274
- data/test/zoneinfo/leapseconds +0 -78
- data/test/zoneinfo/posix/Europe/London +0 -0
- data/test/zoneinfo/posixrules +0 -0
- data/test/zoneinfo/right/Europe/London +0 -0
- data/test/zoneinfo/zone.tab +0 -452
- data/test/zoneinfo/zone1970.tab +0 -384
- data/tzinfo.gemspec +0 -21
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
module TZInfo
|
|
2
|
-
# Raised if no offsets have been defined when calling period_for_utc or
|
|
3
|
-
# periods_for_local. Indicates an error in the timezone data.
|
|
4
|
-
class NoOffsetsDefined < StandardError
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
# Represents a data timezone defined by a set of offsets and a set
|
|
8
|
-
# of transitions.
|
|
9
|
-
#
|
|
10
|
-
# @private
|
|
11
|
-
class TransitionDataTimezoneInfo < DataTimezoneInfo #:nodoc:
|
|
12
|
-
|
|
13
|
-
# Constructs a new TransitionDataTimezoneInfo with its identifier.
|
|
14
|
-
def initialize(identifier)
|
|
15
|
-
super(identifier)
|
|
16
|
-
@offsets = {}
|
|
17
|
-
@transitions = []
|
|
18
|
-
@previous_offset = nil
|
|
19
|
-
@transitions_index = nil
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Defines a offset. The id uniquely identifies this offset within the
|
|
23
|
-
# timezone. utc_offset and std_offset define the offset in seconds of
|
|
24
|
-
# standard time from UTC and daylight savings from standard time
|
|
25
|
-
# respectively. abbreviation describes the timezone offset (e.g. GMT, BST,
|
|
26
|
-
# EST or EDT).
|
|
27
|
-
#
|
|
28
|
-
# The first offset to be defined is treated as the offset that applies
|
|
29
|
-
# until the first transition. This will usually be in Local Mean Time (LMT).
|
|
30
|
-
#
|
|
31
|
-
# ArgumentError will be raised if the id is already defined.
|
|
32
|
-
def offset(id, utc_offset, std_offset, abbreviation)
|
|
33
|
-
raise ArgumentError, 'Offset already defined' if @offsets.has_key?(id)
|
|
34
|
-
|
|
35
|
-
offset = TimezoneOffset.new(utc_offset, std_offset, abbreviation)
|
|
36
|
-
@offsets[id] = offset
|
|
37
|
-
@previous_offset = offset unless @previous_offset
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Defines a transition. Transitions must be defined in chronological order.
|
|
41
|
-
# ArgumentError will be raised if a transition is added out of order.
|
|
42
|
-
# offset_id refers to an id defined with offset. ArgumentError will be
|
|
43
|
-
# raised if the offset_id cannot be found. numerator_or_time and
|
|
44
|
-
# denomiator specify the time the transition occurs as. See
|
|
45
|
-
# TimezoneTransition for more detail about specifying times.
|
|
46
|
-
def transition(year, month, offset_id, numerator_or_timestamp, denominator_or_numerator = nil, denominator = nil)
|
|
47
|
-
offset = @offsets[offset_id]
|
|
48
|
-
raise ArgumentError, 'Offset not found' unless offset
|
|
49
|
-
|
|
50
|
-
if @transitions_index
|
|
51
|
-
if year < @last_year || (year == @last_year && month < @last_month)
|
|
52
|
-
raise ArgumentError, 'Transitions must be increasing date order'
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Record the position of the first transition with this index.
|
|
56
|
-
index = transition_index(year, month)
|
|
57
|
-
@transitions_index[index] ||= @transitions.length
|
|
58
|
-
|
|
59
|
-
# Fill in any gaps
|
|
60
|
-
(index - 1).downto(0) do |i|
|
|
61
|
-
break if @transitions_index[i]
|
|
62
|
-
@transitions_index[i] = @transitions.length
|
|
63
|
-
end
|
|
64
|
-
else
|
|
65
|
-
@transitions_index = [@transitions.length]
|
|
66
|
-
@start_year = year
|
|
67
|
-
@start_month = month
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
@transitions << TimezoneTransitionDefinition.new(offset, @previous_offset,
|
|
71
|
-
numerator_or_timestamp, denominator_or_numerator, denominator)
|
|
72
|
-
@last_year = year
|
|
73
|
-
@last_month = month
|
|
74
|
-
@previous_offset = offset
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Returns the TimezonePeriod for the given UTC time.
|
|
78
|
-
# Raises NoOffsetsDefined if no offsets have been defined.
|
|
79
|
-
def period_for_utc(utc)
|
|
80
|
-
unless @transitions.empty?
|
|
81
|
-
utc = TimeOrDateTime.wrap(utc)
|
|
82
|
-
index = transition_index(utc.year, utc.mon)
|
|
83
|
-
|
|
84
|
-
start_transition = nil
|
|
85
|
-
start = transition_before_end(index)
|
|
86
|
-
if start
|
|
87
|
-
start.downto(0) do |i|
|
|
88
|
-
if @transitions[i].at <= utc
|
|
89
|
-
start_transition = @transitions[i]
|
|
90
|
-
break
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
end_transition = nil
|
|
96
|
-
start = transition_after_start(index)
|
|
97
|
-
if start
|
|
98
|
-
start.upto(@transitions.length - 1) do |i|
|
|
99
|
-
if @transitions[i].at > utc
|
|
100
|
-
end_transition = @transitions[i]
|
|
101
|
-
break
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
if start_transition || end_transition
|
|
107
|
-
TimezonePeriod.new(start_transition, end_transition)
|
|
108
|
-
else
|
|
109
|
-
# Won't happen since there are transitions. Must always find one
|
|
110
|
-
# transition that is either >= or < the specified time.
|
|
111
|
-
raise 'No transitions found in search'
|
|
112
|
-
end
|
|
113
|
-
else
|
|
114
|
-
raise NoOffsetsDefined, 'No offsets have been defined' unless @previous_offset
|
|
115
|
-
TimezonePeriod.new(nil, nil, @previous_offset)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Returns the set of TimezonePeriods for the given local time as an array.
|
|
120
|
-
# Results returned are ordered by increasing UTC start date.
|
|
121
|
-
# Returns an empty array if no periods are found for the given time.
|
|
122
|
-
# Raises NoOffsetsDefined if no offsets have been defined.
|
|
123
|
-
def periods_for_local(local)
|
|
124
|
-
unless @transitions.empty?
|
|
125
|
-
local = TimeOrDateTime.wrap(local)
|
|
126
|
-
index = transition_index(local.year, local.mon)
|
|
127
|
-
|
|
128
|
-
result = []
|
|
129
|
-
|
|
130
|
-
start_index = transition_after_start(index - 1)
|
|
131
|
-
if start_index && @transitions[start_index].local_end_at > local
|
|
132
|
-
if start_index > 0
|
|
133
|
-
if @transitions[start_index - 1].local_start_at <= local
|
|
134
|
-
result << TimezonePeriod.new(@transitions[start_index - 1], @transitions[start_index])
|
|
135
|
-
end
|
|
136
|
-
else
|
|
137
|
-
result << TimezonePeriod.new(nil, @transitions[start_index])
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
end_index = transition_before_end(index + 1)
|
|
142
|
-
|
|
143
|
-
if end_index
|
|
144
|
-
start_index = end_index unless start_index
|
|
145
|
-
|
|
146
|
-
start_index.upto(transition_before_end(index + 1)) do |i|
|
|
147
|
-
if @transitions[i].local_start_at <= local
|
|
148
|
-
if i + 1 < @transitions.length
|
|
149
|
-
if @transitions[i + 1].local_end_at > local
|
|
150
|
-
result << TimezonePeriod.new(@transitions[i], @transitions[i + 1])
|
|
151
|
-
end
|
|
152
|
-
else
|
|
153
|
-
result << TimezonePeriod.new(@transitions[i], nil)
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
result
|
|
160
|
-
else
|
|
161
|
-
raise NoOffsetsDefined, 'No offsets have been defined' unless @previous_offset
|
|
162
|
-
[TimezonePeriod.new(nil, nil, @previous_offset)]
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Returns an Array of TimezoneTransition instances representing the times
|
|
167
|
-
# where the UTC offset of the timezone changes.
|
|
168
|
-
#
|
|
169
|
-
# Transitions are returned up to a given date and time up to a given date
|
|
170
|
-
# and time, specified in UTC (utc_to).
|
|
171
|
-
#
|
|
172
|
-
# A from date and time may also be supplied using the utc_from parameter
|
|
173
|
-
# (also specified in UTC). If utc_from is not nil, only transitions from
|
|
174
|
-
# that date and time onwards will be returned.
|
|
175
|
-
#
|
|
176
|
-
# Comparisons with utc_to are exclusive. Comparisons with utc_from are
|
|
177
|
-
# inclusive. If a transition falls precisely on utc_to, it will be excluded.
|
|
178
|
-
# If a transition falls on utc_from, it will be included.
|
|
179
|
-
#
|
|
180
|
-
# Transitions returned are ordered by when they occur, from earliest to
|
|
181
|
-
# latest.
|
|
182
|
-
#
|
|
183
|
-
# utc_to and utc_from can be specified using either DateTime, Time or
|
|
184
|
-
# integer timestamps (Time.to_i).
|
|
185
|
-
#
|
|
186
|
-
# If utc_from is specified and utc_to is not greater than utc_from, then
|
|
187
|
-
# transitions_up_to raises an ArgumentError exception.
|
|
188
|
-
def transitions_up_to(utc_to, utc_from = nil)
|
|
189
|
-
utc_to = TimeOrDateTime.wrap(utc_to)
|
|
190
|
-
utc_from = utc_from ? TimeOrDateTime.wrap(utc_from) : nil
|
|
191
|
-
|
|
192
|
-
if utc_from && utc_to <= utc_from
|
|
193
|
-
raise ArgumentError, 'utc_to must be greater than utc_from'
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
unless @transitions.empty?
|
|
197
|
-
if utc_from
|
|
198
|
-
from = transition_after_start(transition_index(utc_from.year, utc_from.mon))
|
|
199
|
-
|
|
200
|
-
if from
|
|
201
|
-
while from < @transitions.length && @transitions[from].at < utc_from
|
|
202
|
-
from += 1
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
if from >= @transitions.length
|
|
206
|
-
return []
|
|
207
|
-
end
|
|
208
|
-
else
|
|
209
|
-
# utc_from is later than last transition.
|
|
210
|
-
return []
|
|
211
|
-
end
|
|
212
|
-
else
|
|
213
|
-
from = 0
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
to = transition_before_end(transition_index(utc_to.year, utc_to.mon))
|
|
217
|
-
|
|
218
|
-
if to
|
|
219
|
-
while to >= 0 && @transitions[to].at >= utc_to
|
|
220
|
-
to -= 1
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
if to < 0
|
|
224
|
-
return []
|
|
225
|
-
end
|
|
226
|
-
else
|
|
227
|
-
# utc_to is earlier than first transition.
|
|
228
|
-
return []
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
@transitions[from..to]
|
|
232
|
-
else
|
|
233
|
-
[]
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
private
|
|
238
|
-
# Returns the index into the @transitions_index array for a given year
|
|
239
|
-
# and month.
|
|
240
|
-
def transition_index(year, month)
|
|
241
|
-
index = (year - @start_year) * 2
|
|
242
|
-
index += 1 if month > 6
|
|
243
|
-
index -= 1 if @start_month > 6
|
|
244
|
-
index
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
# Returns the index into @transitions of the first transition that occurs
|
|
248
|
-
# on or after the start of the given index into @transitions_index.
|
|
249
|
-
# Returns nil if there are no such transitions.
|
|
250
|
-
def transition_after_start(index)
|
|
251
|
-
if index >= @transitions_index.length
|
|
252
|
-
nil
|
|
253
|
-
else
|
|
254
|
-
index = 0 if index < 0
|
|
255
|
-
@transitions_index[index]
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
# Returns the index into @transitions of the first transition that occurs
|
|
260
|
-
# before the end of the given index into @transitions_index.
|
|
261
|
-
# Returns nil if there are no such transitions.
|
|
262
|
-
def transition_before_end(index)
|
|
263
|
-
index = index + 1
|
|
264
|
-
|
|
265
|
-
if index <= 0
|
|
266
|
-
nil
|
|
267
|
-
elsif index >= @transitions_index.length
|
|
268
|
-
@transitions.length - 1
|
|
269
|
-
else
|
|
270
|
-
@transitions_index[index] - 1
|
|
271
|
-
end
|
|
272
|
-
end
|
|
273
|
-
end
|
|
274
|
-
end
|
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
require 'date'
|
|
2
|
-
|
|
3
|
-
module TZInfo
|
|
4
|
-
# Base class for rules definining the transition between standard and daylight
|
|
5
|
-
# savings time.
|
|
6
|
-
class TransitionRule #:nodoc:
|
|
7
|
-
# Returns the number of seconds after midnight local time on the day
|
|
8
|
-
# identified by the rule at which the transition occurs. Can be negative to
|
|
9
|
-
# denote a time on the prior day. Can be greater than or equal to 86,400 to
|
|
10
|
-
# denote a time of the following day.
|
|
11
|
-
attr_reader :transition_at
|
|
12
|
-
|
|
13
|
-
# Initializes a new TransitionRule.
|
|
14
|
-
def initialize(transition_at)
|
|
15
|
-
raise ArgumentError, 'Invalid transition_at' unless transition_at.kind_of?(Integer)
|
|
16
|
-
@transition_at = transition_at
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Calculates the UTC time of the transition from a given offset on a given
|
|
20
|
-
# year.
|
|
21
|
-
def at(offset, year)
|
|
22
|
-
day = get_day(year)
|
|
23
|
-
day.add_with_convert(@transition_at - offset.utc_total_offset)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Determines if this TransitionRule is equal to another instance.
|
|
27
|
-
def ==(r)
|
|
28
|
-
r.kind_of?(TransitionRule) && @transition_at == r.transition_at
|
|
29
|
-
end
|
|
30
|
-
alias eql? ==
|
|
31
|
-
|
|
32
|
-
# Returns a hash based on hash_args (defaulting to transition_at).
|
|
33
|
-
def hash
|
|
34
|
-
hash_args.hash
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
protected
|
|
38
|
-
|
|
39
|
-
# Returns an Array of parameters that will influence the output of hash.
|
|
40
|
-
def hash_args
|
|
41
|
-
[@transition_at]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def new_time_or_datetime(year, month = 1, day = 1)
|
|
45
|
-
result = if ((year >= 2039 || (year == 2038 && (month >= 2 || (month == 1 && day >= 20)))) && !RubyCoreSupport.time_supports_64bit) ||
|
|
46
|
-
(year < 1970 && !RubyCoreSupport.time_supports_negative)
|
|
47
|
-
|
|
48
|
-
# Time handles 29 February on a non-leap year as 1 March.
|
|
49
|
-
# DateTime rejects. Advance manually.
|
|
50
|
-
if month == 2 && day == 29 && !Date.gregorian_leap?(year)
|
|
51
|
-
month = 3
|
|
52
|
-
day = 1
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
RubyCoreSupport.datetime_new(year, month, day)
|
|
56
|
-
else
|
|
57
|
-
Time.utc(year, month, day)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
TimeOrDateTime.wrap(result)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# A base class for transition rules that activate based on an integer day of
|
|
65
|
-
# the year.
|
|
66
|
-
#
|
|
67
|
-
# @private
|
|
68
|
-
class DayOfYearTransitionRule < TransitionRule #:nodoc:
|
|
69
|
-
# Initializes a new DayOfYearTransitionRule.
|
|
70
|
-
def initialize(day, transition_at)
|
|
71
|
-
super(transition_at)
|
|
72
|
-
raise ArgumentError, 'Invalid day' unless day.kind_of?(Integer)
|
|
73
|
-
@seconds = day * 86400
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Determines if this DayOfYearTransitionRule is equal to another instance.
|
|
77
|
-
def ==(r)
|
|
78
|
-
super(r) && r.kind_of?(DayOfYearTransitionRule) && @seconds == r.seconds
|
|
79
|
-
end
|
|
80
|
-
alias eql? ==
|
|
81
|
-
|
|
82
|
-
protected
|
|
83
|
-
|
|
84
|
-
# @return [Integer] the day multipled by the number of seconds in a day.
|
|
85
|
-
attr_reader :seconds
|
|
86
|
-
|
|
87
|
-
# Returns an Array of parameters that will influence the output of hash.
|
|
88
|
-
def hash_args
|
|
89
|
-
[@seconds] + super
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Defines transitions that occur on the zero-based nth day of the year.
|
|
94
|
-
#
|
|
95
|
-
# Day 0 is 1 January.
|
|
96
|
-
#
|
|
97
|
-
# Leap days are counted. Day 59 will be 29 February on a leap year and 1 March
|
|
98
|
-
# on a non-leap year. Day 365 will be 31 December on a leap year and 1 January
|
|
99
|
-
# the following year on a non-leap year.
|
|
100
|
-
#
|
|
101
|
-
# @private
|
|
102
|
-
class AbsoluteDayOfYearTransitionRule < DayOfYearTransitionRule #:nodoc:
|
|
103
|
-
# Initializes a new AbsoluteDayOfYearTransitionRule.
|
|
104
|
-
def initialize(day, transition_at = 0)
|
|
105
|
-
super(day, transition_at)
|
|
106
|
-
raise ArgumentError, 'Invalid day' unless day >= 0 && day <= 365
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Returns true if the day specified by this transition is the first in the
|
|
110
|
-
# year (a day number of 0), otherwise false.
|
|
111
|
-
def is_always_first_day_of_year?
|
|
112
|
-
seconds == 0
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# @returns false.
|
|
116
|
-
def is_always_last_day_of_year?
|
|
117
|
-
false
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# Determines if this AbsoluteDayOfYearTransitionRule is equal to another
|
|
121
|
-
# instance.
|
|
122
|
-
def ==(r)
|
|
123
|
-
super(r) && r.kind_of?(AbsoluteDayOfYearTransitionRule)
|
|
124
|
-
end
|
|
125
|
-
alias eql? ==
|
|
126
|
-
|
|
127
|
-
protected
|
|
128
|
-
|
|
129
|
-
# Returns a TimeOrDateTime representing midnight local time on the day
|
|
130
|
-
# specified by the rule for the given offset and year.
|
|
131
|
-
def get_day(year)
|
|
132
|
-
new_time_or_datetime(year).add_with_convert(seconds)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
# Returns an Array of parameters that will influence the output of hash.
|
|
136
|
-
def hash_args
|
|
137
|
-
[AbsoluteDayOfYearTransitionRule] + super
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Defines transitions that occur on the one-based nth Julian day of the year.
|
|
142
|
-
#
|
|
143
|
-
# Leap days are not counted. Day 1 is 1 January. Day 60 is always 1 March.
|
|
144
|
-
# Day 365 is always 31 December.
|
|
145
|
-
#
|
|
146
|
-
# @private
|
|
147
|
-
class JulianDayOfYearTransitionRule < DayOfYearTransitionRule #:nodoc:
|
|
148
|
-
# The 60 days in seconds.
|
|
149
|
-
LEAP = 60 * 86400
|
|
150
|
-
|
|
151
|
-
# The length of a non-leap year in seconds.
|
|
152
|
-
YEAR = 365 * 86400
|
|
153
|
-
|
|
154
|
-
# Initializes a new JulianDayOfYearTransitionRule.
|
|
155
|
-
def initialize(day, transition_at = 0)
|
|
156
|
-
super(day, transition_at)
|
|
157
|
-
raise ArgumentError, 'Invalid day' unless day >= 1 && day <= 365
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Returns true if the day specified by this transition is the first in the
|
|
161
|
-
# year (a day number of 1), otherwise false.
|
|
162
|
-
def is_always_first_day_of_year?
|
|
163
|
-
seconds == 86400
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Returns true if the day specified by this transition is the last in the
|
|
167
|
-
# year (a day number of 365), otherwise false.
|
|
168
|
-
def is_always_last_day_of_year?
|
|
169
|
-
seconds == YEAR
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
# Determines if this JulianDayOfYearTransitionRule is equal to another
|
|
173
|
-
# instance.
|
|
174
|
-
def ==(r)
|
|
175
|
-
super(r) && r.kind_of?(JulianDayOfYearTransitionRule)
|
|
176
|
-
end
|
|
177
|
-
alias eql? ==
|
|
178
|
-
|
|
179
|
-
protected
|
|
180
|
-
|
|
181
|
-
# Returns a TimeOrDateTime representing midnight local time on the day
|
|
182
|
-
# specified by the rule for the given offset and year.
|
|
183
|
-
def get_day(year)
|
|
184
|
-
# Returns 1 March on non-leap years.
|
|
185
|
-
leap = new_time_or_datetime(year, 2, 29)
|
|
186
|
-
diff = seconds - LEAP
|
|
187
|
-
diff += 86400 if diff >= 0 && leap.mday == 29
|
|
188
|
-
leap.add_with_convert(diff)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
# Returns an Array of parameters that will influence the output of hash.
|
|
192
|
-
def hash_args
|
|
193
|
-
[JulianDayOfYearTransitionRule] + super
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
# A base class for rules that transition on a particular day of week of a
|
|
198
|
-
# given week (subclasses specify which week of the month).
|
|
199
|
-
#
|
|
200
|
-
# @private
|
|
201
|
-
class DayOfWeekTransitionRule < TransitionRule #:nodoc:
|
|
202
|
-
# Initializes a new DayOfWeekTransitionRule.
|
|
203
|
-
def initialize(month, day_of_week, transition_at)
|
|
204
|
-
super(transition_at)
|
|
205
|
-
raise ArgumentError, 'Invalid month' unless month.kind_of?(Integer) && month >= 1 && month <= 12
|
|
206
|
-
raise ArgumentError, 'Invalid day_of_week' unless day_of_week.kind_of?(Integer) && day_of_week >= 0 && day_of_week <= 6
|
|
207
|
-
@month = month
|
|
208
|
-
@day_of_week = day_of_week
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
# Returns false.
|
|
212
|
-
def is_always_first_day_of_year?
|
|
213
|
-
false
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
# Returns false.
|
|
217
|
-
def is_always_last_day_of_year?
|
|
218
|
-
false
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
# Determines if this DayOfWeekTransitionRule is equal to another instance.
|
|
222
|
-
def ==(r)
|
|
223
|
-
super(r) && r.kind_of?(DayOfWeekTransitionRule) && @month == r.month && @day_of_week == r.day_of_week
|
|
224
|
-
end
|
|
225
|
-
alias eql? ==
|
|
226
|
-
|
|
227
|
-
protected
|
|
228
|
-
|
|
229
|
-
# Returns the month of the year (1 to 12).
|
|
230
|
-
attr_reader :month
|
|
231
|
-
|
|
232
|
-
# Returns the day of the week (0 to 6 for Sunday to Monday).
|
|
233
|
-
attr_reader :day_of_week
|
|
234
|
-
|
|
235
|
-
# Returns an Array of parameters that will influence the output of hash.
|
|
236
|
-
def hash_args
|
|
237
|
-
[@month, @day_of_week] + super
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
# A rule that transitions on the nth occurrence of a particular day of week
|
|
242
|
-
# of a calendar month.
|
|
243
|
-
#
|
|
244
|
-
# @private
|
|
245
|
-
class DayOfMonthTransitionRule < DayOfWeekTransitionRule #:nodoc:
|
|
246
|
-
# Initializes a new DayOfMonthTransitionRule.
|
|
247
|
-
def initialize(month, week, day_of_week, transition_at = 0)
|
|
248
|
-
super(month, day_of_week, transition_at)
|
|
249
|
-
raise ArgumentError, 'Invalid week' unless week.kind_of?(Integer) && week >= 1 && week <= 4
|
|
250
|
-
@offset_start = (week - 1) * 7 + 1
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
# Determines if this DayOfMonthTransitionRule is equal to another instance.
|
|
254
|
-
def ==(r)
|
|
255
|
-
super(r) && r.kind_of?(DayOfMonthTransitionRule) && @offset_start == r.offset_start
|
|
256
|
-
end
|
|
257
|
-
alias eql? ==
|
|
258
|
-
|
|
259
|
-
protected
|
|
260
|
-
|
|
261
|
-
# Returns the day the week starts on for a month starting on a Sunday.
|
|
262
|
-
attr_reader :offset_start
|
|
263
|
-
|
|
264
|
-
# Returns a TimeOrDateTime representing midnight local time on the day
|
|
265
|
-
# specified by the rule for the given offset and year.
|
|
266
|
-
def get_day(year)
|
|
267
|
-
candidate = new_time_or_datetime(year, month, @offset_start)
|
|
268
|
-
diff = day_of_week - candidate.wday
|
|
269
|
-
|
|
270
|
-
if diff < 0
|
|
271
|
-
candidate.add_with_convert((7 + diff) * 86400)
|
|
272
|
-
elsif diff > 0
|
|
273
|
-
candidate.add_with_convert(diff * 86400)
|
|
274
|
-
else
|
|
275
|
-
candidate
|
|
276
|
-
end
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
# Returns an Array of parameters that will influence the output of hash.
|
|
280
|
-
def hash_args
|
|
281
|
-
[@offset_start] + super
|
|
282
|
-
end
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
# A rule that transitions on the last occurrence of a particular day of week
|
|
286
|
-
# of a calendar month.
|
|
287
|
-
#
|
|
288
|
-
# @private
|
|
289
|
-
class LastDayOfMonthTransitionRule < DayOfWeekTransitionRule #:nodoc:
|
|
290
|
-
# Initializes a new LastDayOfMonthTransitionRule.
|
|
291
|
-
def initialize(month, day_of_week, transition_at = 0)
|
|
292
|
-
super(month, day_of_week, transition_at)
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
# Determines if this LastDayOfMonthTransitionRule is equal to another
|
|
296
|
-
# instance.
|
|
297
|
-
def ==(r)
|
|
298
|
-
super(r) && r.kind_of?(LastDayOfMonthTransitionRule)
|
|
299
|
-
end
|
|
300
|
-
alias eql? ==
|
|
301
|
-
|
|
302
|
-
protected
|
|
303
|
-
|
|
304
|
-
# Returns a TimeOrDateTime representing midnight local time on the day
|
|
305
|
-
# specified by the rule for the given offset and year.
|
|
306
|
-
def get_day(year)
|
|
307
|
-
next_month = month + 1
|
|
308
|
-
if next_month == 13
|
|
309
|
-
year += 1
|
|
310
|
-
next_month = 1
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
candidate = new_time_or_datetime(year, next_month).add_with_convert(-86400)
|
|
314
|
-
diff = candidate.wday - day_of_week
|
|
315
|
-
|
|
316
|
-
if diff < 0
|
|
317
|
-
candidate - (diff + 7) * 86400
|
|
318
|
-
elsif diff > 0
|
|
319
|
-
candidate - diff * 86400
|
|
320
|
-
else
|
|
321
|
-
candidate
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
module TZInfo
|
|
2
|
-
# Represents information about a country returned by ZoneinfoDataSource.
|
|
3
|
-
#
|
|
4
|
-
# @private
|
|
5
|
-
class ZoneinfoCountryInfo < CountryInfo #:nodoc:
|
|
6
|
-
# Constructs a new CountryInfo with an ISO 3166 country code, name and
|
|
7
|
-
# an array of CountryTimezones.
|
|
8
|
-
def initialize(code, name, zones)
|
|
9
|
-
super(code, name)
|
|
10
|
-
@zones = zones.dup.freeze
|
|
11
|
-
@zone_identifiers = nil
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Returns a frozen array of all the zone identifiers for the country ordered
|
|
15
|
-
# geographically, most populous first.
|
|
16
|
-
def zone_identifiers
|
|
17
|
-
# Thread-safety: It is possible that the value of @zone_identifiers may be
|
|
18
|
-
# calculated multiple times in concurrently executing threads. It is not
|
|
19
|
-
# worth the overhead of locking to ensure that @zone_identifiers is only
|
|
20
|
-
# calculated once.
|
|
21
|
-
|
|
22
|
-
unless @zone_identifiers
|
|
23
|
-
result = zones.collect {|zone| zone.identifier}.freeze
|
|
24
|
-
return result if frozen?
|
|
25
|
-
@zone_identifiers = result
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
@zone_identifiers
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Returns a frozen array of all the timezones for the for the country
|
|
32
|
-
# ordered geographically, most populous first.
|
|
33
|
-
def zones
|
|
34
|
-
@zones
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|