tzinfo-data 1.2018.7 → 1.2018.8
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 +1 -2
- data.tar.gz.sig +0 -0
- data/LICENSE +12 -12
- data/README.md +2 -2
- data/lib/tzinfo/data/definitions/Africa/Casablanca.rb +42 -1
- data/lib/tzinfo/data/definitions/Africa/El_Aaiun.rb +42 -1
- data/lib/tzinfo/data/definitions/America/Metlakatla.rb +1 -1
- data/lib/tzinfo/data/definitions/Asia/Hong_Kong.rb +8 -7
- data/lib/tzinfo/data/definitions/Asia/Qostanay.rb +77 -0
- data/lib/tzinfo/data/definitions/Asia/Qyzylorda.rb +1 -0
- data/lib/tzinfo/data/definitions/Asia/Tehran.rb +28 -28
- data/lib/tzinfo/data/definitions/Pacific/Chuuk.rb +10 -3
- data/lib/tzinfo/data/definitions/Pacific/Guam.rb +22 -2
- data/lib/tzinfo/data/definitions/Pacific/Kosrae.rb +15 -6
- data/lib/tzinfo/data/definitions/Pacific/Kwajalein.rb +9 -4
- data/lib/tzinfo/data/definitions/Pacific/Majuro.rb +9 -2
- data/lib/tzinfo/data/definitions/Pacific/Nauru.rb +3 -3
- data/lib/tzinfo/data/definitions/Pacific/Palau.rb +5 -3
- data/lib/tzinfo/data/definitions/Pacific/Pohnpei.rb +12 -3
- data/lib/tzinfo/data/indexes/countries.rb +2 -1
- data/lib/tzinfo/data/indexes/timezones.rb +1 -0
- data/lib/tzinfo/data/tzdataparser.rb +322 -322
- data/lib/tzinfo/data/version.rb +4 -4
- metadata +4 -4
- metadata.gz.sig +0 -0
|
@@ -11,13 +11,22 @@ module TZInfo
|
|
|
11
11
|
include TimezoneDefinition
|
|
12
12
|
|
|
13
13
|
timezone 'Pacific/Kosrae' do |tz|
|
|
14
|
-
tz.offset :o0,
|
|
15
|
-
tz.offset :o1,
|
|
16
|
-
tz.offset :o2,
|
|
14
|
+
tz.offset :o0, -47284, 0, :LMT
|
|
15
|
+
tz.offset :o1, 39116, 0, :LMT
|
|
16
|
+
tz.offset :o2, 39600, 0, :'+11'
|
|
17
|
+
tz.offset :o3, 32400, 0, :'+09'
|
|
18
|
+
tz.offset :o4, 36000, 0, :'+10'
|
|
19
|
+
tz.offset :o5, 43200, 0, :'+12'
|
|
17
20
|
|
|
18
|
-
tz.transition
|
|
19
|
-
tz.transition
|
|
20
|
-
tz.transition
|
|
21
|
+
tz.transition 1844, 12, :o1, -3944631116, 51730532221, 21600
|
|
22
|
+
tz.transition 1900, 12, :o2, -2177491916, 52172317021, 21600
|
|
23
|
+
tz.transition 1914, 9, :o3, -1743678000, 58089745, 24
|
|
24
|
+
tz.transition 1919, 1, :o2, -1606813200, 19375921, 8
|
|
25
|
+
tz.transition 1936, 12, :o4, -1041418800, 58284817, 24
|
|
26
|
+
tz.transition 1941, 3, :o3, -907408800, 29161021, 12
|
|
27
|
+
tz.transition 1945, 7, :o2, -770634000, 19453345, 8
|
|
28
|
+
tz.transition 1969, 9, :o5, -7988400, 58571881, 24
|
|
29
|
+
tz.transition 1998, 12, :o2, 915105600
|
|
21
30
|
end
|
|
22
31
|
end
|
|
23
32
|
end
|
|
@@ -13,12 +13,17 @@ module TZInfo
|
|
|
13
13
|
timezone 'Pacific/Kwajalein' do |tz|
|
|
14
14
|
tz.offset :o0, 40160, 0, :LMT
|
|
15
15
|
tz.offset :o1, 39600, 0, :'+11'
|
|
16
|
-
tz.offset :o2,
|
|
17
|
-
tz.offset :o3,
|
|
16
|
+
tz.offset :o2, 36000, 0, :'+10'
|
|
17
|
+
tz.offset :o3, 32400, 0, :'+09'
|
|
18
|
+
tz.offset :o4, -43200, 0, :'-12'
|
|
19
|
+
tz.offset :o5, 43200, 0, :'+12'
|
|
18
20
|
|
|
19
21
|
tz.transition 1900, 12, :o1, -2177492960, 1304307919, 540
|
|
20
|
-
tz.transition
|
|
21
|
-
tz.transition
|
|
22
|
+
tz.transition 1936, 12, :o2, -1041418800, 58284817, 24
|
|
23
|
+
tz.transition 1941, 3, :o3, -907408800, 29161021, 12
|
|
24
|
+
tz.transition 1944, 2, :o1, -817462800, 19449009, 8
|
|
25
|
+
tz.transition 1969, 9, :o4, -7988400, 58571881, 24
|
|
26
|
+
tz.transition 1993, 8, :o5, 745934400
|
|
22
27
|
end
|
|
23
28
|
end
|
|
24
29
|
end
|
|
@@ -13,10 +13,17 @@ module TZInfo
|
|
|
13
13
|
timezone 'Pacific/Majuro' do |tz|
|
|
14
14
|
tz.offset :o0, 41088, 0, :LMT
|
|
15
15
|
tz.offset :o1, 39600, 0, :'+11'
|
|
16
|
-
tz.offset :o2,
|
|
16
|
+
tz.offset :o2, 32400, 0, :'+09'
|
|
17
|
+
tz.offset :o3, 36000, 0, :'+10'
|
|
18
|
+
tz.offset :o4, 43200, 0, :'+12'
|
|
17
19
|
|
|
18
20
|
tz.transition 1900, 12, :o1, -2177493888, 1086923261, 450
|
|
19
|
-
tz.transition
|
|
21
|
+
tz.transition 1914, 9, :o2, -1743678000, 58089745, 24
|
|
22
|
+
tz.transition 1919, 1, :o1, -1606813200, 19375921, 8
|
|
23
|
+
tz.transition 1936, 12, :o3, -1041418800, 58284817, 24
|
|
24
|
+
tz.transition 1941, 3, :o2, -907408800, 29161021, 12
|
|
25
|
+
tz.transition 1944, 1, :o1, -818067600, 19448953, 8
|
|
26
|
+
tz.transition 1969, 9, :o4, -7988400, 58571881, 24
|
|
20
27
|
end
|
|
21
28
|
end
|
|
22
29
|
end
|
|
@@ -17,9 +17,9 @@ module TZInfo
|
|
|
17
17
|
tz.offset :o3, 43200, 0, :'+12'
|
|
18
18
|
|
|
19
19
|
tz.transition 1921, 1, :o1, -1545131260, 10466081437, 4320
|
|
20
|
-
tz.transition 1942,
|
|
21
|
-
tz.transition
|
|
22
|
-
tz.transition 1979,
|
|
20
|
+
tz.transition 1942, 8, :o2, -862918200, 116668801, 48
|
|
21
|
+
tz.transition 1945, 9, :o1, -767350800, 19453649, 8
|
|
22
|
+
tz.transition 1979, 2, :o3, 287418600
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -11,10 +11,12 @@ module TZInfo
|
|
|
11
11
|
include TimezoneDefinition
|
|
12
12
|
|
|
13
13
|
timezone 'Pacific/Palau' do |tz|
|
|
14
|
-
tz.offset :o0,
|
|
15
|
-
tz.offset :o1,
|
|
14
|
+
tz.offset :o0, -54124, 0, :LMT
|
|
15
|
+
tz.offset :o1, 32276, 0, :LMT
|
|
16
|
+
tz.offset :o2, 32400, 0, :'+09'
|
|
16
17
|
|
|
17
|
-
tz.transition
|
|
18
|
+
tz.transition 1844, 12, :o1, -3944624276, 51730533931, 21600
|
|
19
|
+
tz.transition 1900, 12, :o2, -2177485076, 52172318731, 21600
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
@@ -11,10 +11,19 @@ module TZInfo
|
|
|
11
11
|
include TimezoneDefinition
|
|
12
12
|
|
|
13
13
|
timezone 'Pacific/Pohnpei' do |tz|
|
|
14
|
-
tz.offset :o0,
|
|
15
|
-
tz.offset :o1,
|
|
14
|
+
tz.offset :o0, -48428, 0, :LMT
|
|
15
|
+
tz.offset :o1, 37972, 0, :LMT
|
|
16
|
+
tz.offset :o2, 39600, 0, :'+11'
|
|
17
|
+
tz.offset :o3, 32400, 0, :'+09'
|
|
18
|
+
tz.offset :o4, 36000, 0, :'+10'
|
|
16
19
|
|
|
17
|
-
tz.transition
|
|
20
|
+
tz.transition 1844, 12, :o1, -3944629972, 51730532507, 21600
|
|
21
|
+
tz.transition 1900, 12, :o2, -2177490772, 52172317307, 21600
|
|
22
|
+
tz.transition 1914, 9, :o3, -1743678000, 58089745, 24
|
|
23
|
+
tz.transition 1919, 1, :o2, -1606813200, 19375921, 8
|
|
24
|
+
tz.transition 1936, 12, :o4, -1041418800, 58284817, 24
|
|
25
|
+
tz.transition 1941, 3, :o3, -907408800, 29161021, 12
|
|
26
|
+
tz.transition 1945, 7, :o2, -770634000, 19453345, 8
|
|
18
27
|
end
|
|
19
28
|
end
|
|
20
29
|
end
|
|
@@ -473,6 +473,7 @@ module TZInfo
|
|
|
473
473
|
country 'KZ', 'Kazakhstan' do |c|
|
|
474
474
|
c.timezone 'Asia/Almaty', 173, 4, 1539, 20, 'Kazakhstan (most areas)'
|
|
475
475
|
c.timezone 'Asia/Qyzylorda', 224, 5, 982, 15, 'Qyzylorda/Kyzylorda/Kzyl-Orda'
|
|
476
|
+
c.timezone 'Asia/Qostanay', 266, 5, 3817, 60, 'Qostanay/Kostanay/Kustanay'
|
|
476
477
|
c.timezone 'Asia/Aqtobe', 3017, 60, 343, 6, 'Aqtöbe/Aktobe'
|
|
477
478
|
c.timezone 'Asia/Aqtau', 2671, 60, 754, 15, 'Mangghystaū/Mankistau'
|
|
478
479
|
c.timezone 'Asia/Atyrau', 2827, 60, 779, 15, 'Atyraū/Atirau/Gur\'yev'
|
|
@@ -698,9 +699,9 @@ module TZInfo
|
|
|
698
699
|
c.timezone 'Europe/Kaliningrad', 3283, 60, 41, 2, 'MSK-01 - Kaliningrad'
|
|
699
700
|
c.timezone 'Europe/Moscow', 66907, 1200, 8464, 225, 'MSK+00 - Moscow area'
|
|
700
701
|
c.timezone 'Europe/Simferopol', 899, 20, 341, 10, 'MSK+00 - Crimea'
|
|
701
|
-
c.timezone 'Europe/Volgograd', 731, 15, 533, 12, 'MSK+00 - Volgograd'
|
|
702
702
|
c.timezone 'Europe/Kirov', 293, 5, 993, 20, 'MSK+00 - Kirov'
|
|
703
703
|
c.timezone 'Europe/Astrakhan', 927, 20, 961, 20, 'MSK+01 - Astrakhan'
|
|
704
|
+
c.timezone 'Europe/Volgograd', 731, 15, 533, 12, 'MSK+01 - Volgograd'
|
|
704
705
|
c.timezone 'Europe/Saratov', 1547, 30, 1381, 30, 'MSK+01 - Saratov'
|
|
705
706
|
c.timezone 'Europe/Ulyanovsk', 163, 3, 242, 5, 'MSK+01 - Ulyanovsk'
|
|
706
707
|
c.timezone 'Europe/Samara', 266, 5, 1003, 20, 'MSK+01 - Samara, Udmurtia'
|
|
@@ -3,7 +3,7 @@ require 'fileutils'
|
|
|
3
3
|
|
|
4
4
|
module TZInfo
|
|
5
5
|
module Data
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
# Utility methods used by TZDataParser and associated classes.
|
|
8
8
|
#
|
|
9
9
|
# @private
|
|
@@ -20,11 +20,11 @@ module TZInfo
|
|
|
20
20
|
File.open(file_name, mode, opts, &block)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
private :open_file
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
private
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
# Parses a month specified in the tz data and converts it to a number
|
|
29
29
|
# between 1 and 12 representing January to December.
|
|
30
30
|
def parse_month(month)
|
|
@@ -57,17 +57,17 @@ module TZInfo
|
|
|
57
57
|
raise "Invalid month: #{month}"
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
# Parses an offset string [-]h:m:s (minutes and seconds are optional). Returns
|
|
62
62
|
# the offset in seconds.
|
|
63
63
|
def parse_offset(offset)
|
|
64
64
|
raise "Invalid time: #{offset}" if offset !~ /^(-)?(?:([0-9]+)(?::([0-9]+)(?::([0-9]+))?)?)?$/
|
|
65
|
-
|
|
66
|
-
negative = !$1.nil?
|
|
65
|
+
|
|
66
|
+
negative = !$1.nil?
|
|
67
67
|
hour = $2.nil? ? 0 : $2.to_i
|
|
68
68
|
minute = $3.nil? ? 0 : $3.to_i
|
|
69
69
|
second = $4.nil? ? 0 : $4.to_i
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
seconds = hour
|
|
72
72
|
seconds = seconds * 60
|
|
73
73
|
seconds = seconds + minute
|
|
@@ -76,52 +76,52 @@ module TZInfo
|
|
|
76
76
|
seconds = -seconds if negative
|
|
77
77
|
seconds
|
|
78
78
|
end
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
# Encloses the string in single quotes and escapes any single quotes in
|
|
81
81
|
# the content.
|
|
82
82
|
def quote_str(str)
|
|
83
83
|
"'#{str.gsub('\'', '\\\\\'')}'"
|
|
84
84
|
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Parses Time Zone Data from the IANA Time Zone Database and transforms it
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Parses Time Zone Data from the IANA Time Zone Database and transforms it
|
|
88
88
|
# into a set of Ruby modules that can be used with TZInfo.
|
|
89
|
-
#
|
|
90
|
-
# Normally, this class wouldn't be used. It is only run to update the
|
|
89
|
+
#
|
|
90
|
+
# Normally, this class wouldn't be used. It is only run to update the
|
|
91
91
|
# timezone data and index modules.
|
|
92
92
|
class TZDataParser
|
|
93
93
|
include TZDataParserUtils
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
# Default earliest year that will be considered.
|
|
96
96
|
DEFAULT_MIN_YEAR = 1800
|
|
97
|
-
|
|
98
|
-
# Default number of future years data to generate (not including the
|
|
97
|
+
|
|
98
|
+
# Default number of future years data to generate (not including the
|
|
99
99
|
# current year).
|
|
100
100
|
DEFAULT_FUTURE_YEARS = 50
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
# Earliest year that will be considered. Defaults to DEFAULT_MIN_YEAR.
|
|
103
103
|
attr_accessor :min_year
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
# Latest year that will be considered. Defaults to the current year plus
|
|
106
106
|
# FUTURE_YEARS.
|
|
107
107
|
attr_accessor :max_year
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
# Whether to generate zone definitions (set to false to stop zones being
|
|
110
|
-
# generated).
|
|
110
|
+
# generated).
|
|
111
111
|
attr_accessor :generate_zones
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
# Whether to generate country definitions (set to false to stop countries
|
|
114
114
|
# being generated).
|
|
115
115
|
attr_accessor :generate_countries
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
# Limit the set of zones to generate (set to an array containing zone
|
|
118
118
|
# identifiers).
|
|
119
119
|
attr_accessor :only_zones
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
# Zones to exclude from generation when not using only_zones (set to an
|
|
122
122
|
# array containing zone identifiers).
|
|
123
123
|
attr_accessor :exclude_zones
|
|
124
|
-
|
|
124
|
+
|
|
125
125
|
# Initializes a new TZDataParser. input_dir must contain the extracted
|
|
126
126
|
# tzdata tarball. output_dir is the location to output the modules
|
|
127
127
|
# (in definitions and indexes directories).
|
|
@@ -140,7 +140,7 @@ module TZInfo
|
|
|
140
140
|
@only_zones = []
|
|
141
141
|
@exclude_zones = []
|
|
142
142
|
end
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
# Reads the tzdata source and generates the classes. Progress information
|
|
145
145
|
# is written to standard out.
|
|
146
146
|
def execute
|
|
@@ -150,20 +150,20 @@ module TZInfo
|
|
|
150
150
|
# install its entries by default.
|
|
151
151
|
|
|
152
152
|
files = Dir.entries(@input_dir).select do |file|
|
|
153
|
-
file =~ /\A[^\.]+\z/ &&
|
|
153
|
+
file =~ /\A[^\.]+\z/ &&
|
|
154
154
|
!%w(backzone calendars leapseconds CONTRIBUTING LICENSE Makefile NEWS README SOURCE Theory version).include?(file) &&
|
|
155
155
|
File.file?(File.join(@input_dir, file))
|
|
156
156
|
end
|
|
157
|
-
|
|
157
|
+
|
|
158
158
|
files.each {|file| load_rules(file) }
|
|
159
159
|
files.each {|file| load_zones(file) }
|
|
160
160
|
files.each {|file| load_links(file) }
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
load_countries
|
|
163
|
-
|
|
163
|
+
|
|
164
164
|
if @generate_zones
|
|
165
165
|
modules = []
|
|
166
|
-
|
|
166
|
+
|
|
167
167
|
if @only_zones.nil? || @only_zones.empty?
|
|
168
168
|
@zones.each_value {|zone|
|
|
169
169
|
zone.write_module(@output_dir) unless @exclude_zones.include?(zone.name)
|
|
@@ -171,45 +171,45 @@ module TZInfo
|
|
|
171
171
|
else
|
|
172
172
|
@only_zones.each {|id|
|
|
173
173
|
zone = @zones[id]
|
|
174
|
-
zone.write_module(@output_dir)
|
|
175
|
-
}
|
|
174
|
+
zone.write_module(@output_dir)
|
|
175
|
+
}
|
|
176
176
|
end
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
write_timezones_index
|
|
179
179
|
end
|
|
180
|
-
|
|
181
|
-
if @generate_countries
|
|
180
|
+
|
|
181
|
+
if @generate_countries
|
|
182
182
|
write_countries_index
|
|
183
183
|
end
|
|
184
184
|
end
|
|
185
|
-
|
|
186
|
-
private
|
|
185
|
+
|
|
186
|
+
private
|
|
187
187
|
# Loads all the Rule definitions from the tz data and stores them in
|
|
188
188
|
# the rule_sets instance variable.
|
|
189
189
|
def load_rules(file)
|
|
190
190
|
puts 'load_rules: ' + file
|
|
191
|
-
|
|
191
|
+
|
|
192
192
|
# Files are in ASCII, but may change to UTF-8 (a superset of ASCII)
|
|
193
193
|
# in the future.
|
|
194
194
|
open_file(File.join(@input_dir, file), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
|
195
195
|
file.each_line do |line|
|
|
196
196
|
line = line.gsub(/#.*$/, '')
|
|
197
197
|
line = line.gsub(/\s+$/, '')
|
|
198
|
-
|
|
198
|
+
|
|
199
199
|
if line =~ /^Rule\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/
|
|
200
|
-
|
|
201
|
-
name = $1
|
|
202
|
-
|
|
203
|
-
if @rule_sets[name].nil?
|
|
204
|
-
@rule_sets[name] = TZDataRuleSet.new(name)
|
|
200
|
+
|
|
201
|
+
name = $1
|
|
202
|
+
|
|
203
|
+
if @rule_sets[name].nil?
|
|
204
|
+
@rule_sets[name] = TZDataRuleSet.new(name)
|
|
205
205
|
end
|
|
206
|
-
|
|
206
|
+
|
|
207
207
|
@rule_sets[name].add_rule(TZDataRule.new($2, $3, $4, $5, $6, $7, $8, $9))
|
|
208
|
-
end
|
|
208
|
+
end
|
|
209
209
|
end
|
|
210
210
|
end
|
|
211
211
|
end
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
# Gets a rules object for the given reference. Might be a named rule set,
|
|
214
214
|
# a fixed offset or an empty ruleset.
|
|
215
215
|
def get_rules(ref)
|
|
@@ -219,80 +219,80 @@ module TZInfo
|
|
|
219
219
|
TZDataFixedOffsetRules.new(parse_offset(ref))
|
|
220
220
|
else
|
|
221
221
|
rule_set = @rule_sets[ref]
|
|
222
|
-
raise "Ruleset not found: #{ref}" if rule_set.nil?
|
|
222
|
+
raise "Ruleset not found: #{ref}" if rule_set.nil?
|
|
223
223
|
rule_set
|
|
224
|
-
end
|
|
224
|
+
end
|
|
225
225
|
end
|
|
226
|
-
|
|
226
|
+
|
|
227
227
|
# Loads in the Zone definitions from the tz data and stores them in @zones.
|
|
228
228
|
def load_zones(file)
|
|
229
229
|
puts 'load_zones: ' + file
|
|
230
|
-
|
|
230
|
+
|
|
231
231
|
in_zone = nil
|
|
232
|
-
|
|
232
|
+
|
|
233
233
|
# Files are in ASCII, but may change to UTF-8 (a superset of ASCII)
|
|
234
234
|
# in the future.
|
|
235
235
|
open_file(File.join(@input_dir, file), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
|
236
236
|
file.each_line do |line|
|
|
237
237
|
line = line.gsub(/#.*$/, '')
|
|
238
238
|
line = line.gsub(/\s+$/, '')
|
|
239
|
-
|
|
239
|
+
|
|
240
240
|
if in_zone
|
|
241
|
-
if line =~ /^\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
|
242
|
-
|
|
241
|
+
if line =~ /^\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
|
242
|
+
|
|
243
243
|
in_zone.add_observance(TZDataObservance.new($1, get_rules($2), $3, $5))
|
|
244
|
-
|
|
245
|
-
in_zone = nil if $4.nil?
|
|
244
|
+
|
|
245
|
+
in_zone = nil if $4.nil?
|
|
246
246
|
end
|
|
247
247
|
else
|
|
248
|
-
if line =~ /^Zone\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
|
248
|
+
if line =~ /^Zone\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)(\s+([0-9]+(\s+.*)?))?$/
|
|
249
249
|
name = $1
|
|
250
|
-
|
|
251
|
-
if @zones[name].nil?
|
|
250
|
+
|
|
251
|
+
if @zones[name].nil?
|
|
252
252
|
@zones[name] = TZDataZone.new(name, @min_year..@max_year)
|
|
253
|
-
end
|
|
254
|
-
|
|
253
|
+
end
|
|
254
|
+
|
|
255
255
|
@zones[name].add_observance(TZDataObservance.new($2, get_rules($3), $4, $6))
|
|
256
|
-
|
|
256
|
+
|
|
257
257
|
in_zone = @zones[name] if !$5.nil?
|
|
258
258
|
end
|
|
259
259
|
end
|
|
260
260
|
end
|
|
261
261
|
end
|
|
262
262
|
end
|
|
263
|
-
|
|
263
|
+
|
|
264
264
|
# Loads in the links and stores them in @zones.
|
|
265
265
|
def load_links(file)
|
|
266
266
|
puts 'load_links: ' + file
|
|
267
|
-
|
|
267
|
+
|
|
268
268
|
# Files are in ASCII, but may change to UTF-8 (a superset of ASCII)
|
|
269
269
|
# in the future.
|
|
270
270
|
open_file(File.join(@input_dir, file), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
|
271
271
|
file.each_line do |line|
|
|
272
272
|
line = line.gsub(/#.*$/, '')
|
|
273
273
|
line = line.gsub(/\s+$/, '')
|
|
274
|
-
|
|
275
|
-
if line =~ /^Link\s+([^\s]+)\s+([^\s]+)/
|
|
276
|
-
name = $2
|
|
274
|
+
|
|
275
|
+
if line =~ /^Link\s+([^\s]+)\s+([^\s]+)/
|
|
276
|
+
name = $2
|
|
277
277
|
link_to = @zones[$1]
|
|
278
278
|
raise "Link to zone not found (#{name}->#{link_to})" if link_to.nil?
|
|
279
279
|
raise "Zone already defined: #{name}" if !@zones[name].nil?
|
|
280
280
|
@zones[name] = TZDataLink.new(name, link_to)
|
|
281
|
-
end
|
|
281
|
+
end
|
|
282
282
|
end
|
|
283
283
|
end
|
|
284
284
|
end
|
|
285
|
-
|
|
285
|
+
|
|
286
286
|
# Loads countries from iso3166.tab and zone1970.tab and stores the
|
|
287
287
|
# result in the countries instance variable.
|
|
288
288
|
def load_countries
|
|
289
289
|
puts 'load_countries'
|
|
290
|
-
|
|
290
|
+
|
|
291
291
|
# iso3166.tab is ASCII encoded, but is planned to change to UTF-8 (a
|
|
292
292
|
# superset of ASCII) in the future.
|
|
293
293
|
open_file(File.join(@input_dir, 'iso3166.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
|
294
294
|
file.each_line do |line|
|
|
295
|
-
|
|
295
|
+
|
|
296
296
|
if line =~ /^([A-Z]{2})\t(.*)$/
|
|
297
297
|
code = $1
|
|
298
298
|
name = $2
|
|
@@ -307,22 +307,22 @@ module TZInfo
|
|
|
307
307
|
# zone1970.tab is UTF-8 encoded.
|
|
308
308
|
open_file(File.join(@input_dir, 'zone1970.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
|
|
309
309
|
file.each_line do |line|
|
|
310
|
-
|
|
311
|
-
line.chomp!
|
|
310
|
+
|
|
311
|
+
line.chomp!
|
|
312
312
|
|
|
313
313
|
if line =~ /^([A-Z]{2}(?:,[A-Z]{2})*)\t([^\t]+)\t([^\t]+)(\t(.*))?$/
|
|
314
314
|
codes = $1
|
|
315
315
|
location_str = $2
|
|
316
316
|
zone_name = $3
|
|
317
317
|
description = $5
|
|
318
|
-
|
|
318
|
+
|
|
319
319
|
location = TZDataLocation.new(location_str)
|
|
320
|
-
|
|
320
|
+
|
|
321
321
|
zone = @zones[zone_name]
|
|
322
|
-
raise "Zone not found: #{zone_name}" if zone.nil?
|
|
323
|
-
|
|
322
|
+
raise "Zone not found: #{zone_name}" if zone.nil?
|
|
323
|
+
|
|
324
324
|
description = nil if description == ''
|
|
325
|
-
|
|
325
|
+
|
|
326
326
|
country_timezone = TZDataCountryTimezone.new(zone, description, location)
|
|
327
327
|
|
|
328
328
|
codes = codes.split(',')
|
|
@@ -347,95 +347,95 @@ module TZInfo
|
|
|
347
347
|
end
|
|
348
348
|
end
|
|
349
349
|
end
|
|
350
|
-
|
|
350
|
+
|
|
351
351
|
# Writes a country index file.
|
|
352
352
|
def write_countries_index
|
|
353
353
|
dir = File.join(@output_dir, 'indexes')
|
|
354
354
|
FileUtils.mkdir_p(dir)
|
|
355
|
-
|
|
355
|
+
|
|
356
356
|
open_file(File.join(dir, 'countries.rb'), 'w', :external_encoding => 'UTF-8', :universal_newline => true) do |file|
|
|
357
357
|
file.puts('# encoding: UTF-8')
|
|
358
358
|
file.puts('')
|
|
359
359
|
file.puts('# This file contains data derived from the IANA Time Zone Database')
|
|
360
360
|
file.puts('# (http://www.iana.org/time-zones).')
|
|
361
361
|
file.puts('')
|
|
362
|
-
|
|
362
|
+
|
|
363
363
|
file.puts('module TZInfo')
|
|
364
364
|
file.puts(' module Data')
|
|
365
365
|
file.puts(' module Indexes')
|
|
366
366
|
file.puts(' module Countries')
|
|
367
367
|
file.puts(' include CountryIndexDefinition')
|
|
368
368
|
file.puts('')
|
|
369
|
-
|
|
370
|
-
countries = @countries.values.sort {|c1,c2| c1.code <=> c2.code}
|
|
369
|
+
|
|
370
|
+
countries = @countries.values.sort {|c1,c2| c1.code <=> c2.code}
|
|
371
371
|
countries.each {|country| country.write_index_record(file)}
|
|
372
|
-
|
|
373
|
-
file.puts(' end') # end module Countries
|
|
372
|
+
|
|
373
|
+
file.puts(' end') # end module Countries
|
|
374
374
|
file.puts(' end') # end module Indexes
|
|
375
375
|
file.puts(' end') # end module Data
|
|
376
376
|
file.puts('end') # end module TZInfo
|
|
377
|
-
end
|
|
377
|
+
end
|
|
378
378
|
end
|
|
379
|
-
|
|
379
|
+
|
|
380
380
|
# Writes a timezone index file.
|
|
381
381
|
def write_timezones_index
|
|
382
382
|
dir = File.join(@output_dir, 'indexes')
|
|
383
383
|
FileUtils.mkdir_p(dir)
|
|
384
|
-
|
|
384
|
+
|
|
385
385
|
open_file(File.join(dir, 'timezones.rb'), 'w', :external_encoding => 'UTF-8', :universal_newline => true) do |file|
|
|
386
386
|
file.puts('# encoding: UTF-8')
|
|
387
387
|
file.puts('')
|
|
388
388
|
file.puts('# This file contains data derived from the IANA Time Zone Database')
|
|
389
389
|
file.puts('# (http://www.iana.org/time-zones).')
|
|
390
390
|
file.puts('')
|
|
391
|
-
|
|
391
|
+
|
|
392
392
|
file.puts('module TZInfo')
|
|
393
393
|
file.puts(' module Data')
|
|
394
394
|
file.puts(' module Indexes')
|
|
395
395
|
file.puts(' module Timezones')
|
|
396
396
|
file.puts(' include TimezoneIndexDefinition')
|
|
397
397
|
file.puts('')
|
|
398
|
-
|
|
398
|
+
|
|
399
399
|
zones = @zones.values.sort {|t1,t2| t1.name <=> t2.name}
|
|
400
400
|
zones.each {|zone| zone.write_index_record(file)}
|
|
401
|
-
|
|
401
|
+
|
|
402
402
|
file.puts(' end') # end module Timezones
|
|
403
403
|
file.puts(' end') # end module Indexes
|
|
404
404
|
file.puts(' end') # end module Data
|
|
405
405
|
file.puts('end') # end module TZInfo
|
|
406
406
|
end
|
|
407
|
-
|
|
407
|
+
|
|
408
408
|
end
|
|
409
409
|
end
|
|
410
|
-
|
|
410
|
+
|
|
411
411
|
# Base class for all rule sets.
|
|
412
412
|
#
|
|
413
413
|
# @private
|
|
414
414
|
class TZDataRules #:nodoc:
|
|
415
415
|
# Name of the rule set, e.g. EU.
|
|
416
416
|
attr_reader :name
|
|
417
|
-
|
|
417
|
+
|
|
418
418
|
def initialize(name)
|
|
419
419
|
@name = name
|
|
420
420
|
end
|
|
421
|
-
|
|
421
|
+
|
|
422
422
|
def count
|
|
423
423
|
0
|
|
424
424
|
end
|
|
425
425
|
end
|
|
426
|
-
|
|
426
|
+
|
|
427
427
|
# Empty rule set with a fixed daylight savings (std) offset.
|
|
428
428
|
#
|
|
429
429
|
# @private
|
|
430
430
|
class TZDataFixedOffsetRules < TZDataRules #:nodoc:
|
|
431
431
|
attr_reader :offset
|
|
432
|
-
|
|
432
|
+
|
|
433
433
|
def initialize(offset)
|
|
434
434
|
super(offset.to_s)
|
|
435
435
|
@offset = offset
|
|
436
|
-
end
|
|
436
|
+
end
|
|
437
437
|
end
|
|
438
|
-
|
|
438
|
+
|
|
439
439
|
# An empty set of rules.
|
|
440
440
|
#
|
|
441
441
|
# @private
|
|
@@ -444,38 +444,38 @@ module TZInfo
|
|
|
444
444
|
super('-')
|
|
445
445
|
end
|
|
446
446
|
end
|
|
447
|
-
|
|
447
|
+
|
|
448
448
|
# A rule set (as defined by Rule name in the tz data).
|
|
449
449
|
#
|
|
450
450
|
# @private
|
|
451
|
-
class TZDataRuleSet < TZDataRules #:nodoc:
|
|
451
|
+
class TZDataRuleSet < TZDataRules #:nodoc:
|
|
452
452
|
attr_reader :rules
|
|
453
|
-
|
|
453
|
+
|
|
454
454
|
def initialize(name)
|
|
455
455
|
super
|
|
456
456
|
@rules = []
|
|
457
457
|
end
|
|
458
|
-
|
|
458
|
+
|
|
459
459
|
# Adds a new rule to the set.
|
|
460
460
|
def add_rule(rule)
|
|
461
461
|
@rules << rule
|
|
462
462
|
end
|
|
463
|
-
|
|
463
|
+
|
|
464
464
|
def count
|
|
465
465
|
@rules.length
|
|
466
466
|
end
|
|
467
|
-
|
|
467
|
+
|
|
468
468
|
def each
|
|
469
469
|
@rules.each {|rule| yield rule}
|
|
470
470
|
end
|
|
471
|
-
end
|
|
472
|
-
|
|
471
|
+
end
|
|
472
|
+
|
|
473
473
|
# A rule in a RuleSet (a single Rule line in the tz data).
|
|
474
474
|
#
|
|
475
475
|
# @private
|
|
476
476
|
class TZDataRule #:nodoc:
|
|
477
477
|
include TZDataParserUtils
|
|
478
|
-
|
|
478
|
+
|
|
479
479
|
attr_reader :from
|
|
480
480
|
attr_reader :to
|
|
481
481
|
attr_reader :type
|
|
@@ -484,15 +484,15 @@ module TZInfo
|
|
|
484
484
|
attr_reader :at_time
|
|
485
485
|
attr_reader :save
|
|
486
486
|
attr_reader :letter
|
|
487
|
-
|
|
487
|
+
|
|
488
488
|
def initialize(from, to, type, in_month, on_day, at_time, save, letter)
|
|
489
489
|
@from = parse_from(from)
|
|
490
490
|
@to = parse_to(to)
|
|
491
|
-
|
|
491
|
+
|
|
492
492
|
# replace a to of :only with the from year
|
|
493
493
|
raise 'to cannot be only if from is minimum' if @to == :only && @from == :min
|
|
494
|
-
@to = @from if @to == :only
|
|
495
|
-
|
|
494
|
+
@to = @from if @to == :only
|
|
495
|
+
|
|
496
496
|
@type = parse_type(type)
|
|
497
497
|
@in_month = parse_month(in_month)
|
|
498
498
|
@on_day = TZDataDayOfMonth.new(on_day)
|
|
@@ -500,22 +500,22 @@ module TZInfo
|
|
|
500
500
|
@save = parse_offset(save)
|
|
501
501
|
@letter = parse_letter(letter)
|
|
502
502
|
end
|
|
503
|
-
|
|
503
|
+
|
|
504
504
|
def activate(year)
|
|
505
505
|
# The following test ignores yearistype at present (currently unused in
|
|
506
506
|
# the data. parse_type currently excepts on encountering a year type.
|
|
507
|
-
if (@from == :min || @from <= year) && (@to == :max || @to >= year)
|
|
507
|
+
if (@from == :min || @from <= year) && (@to == :max || @to >= year)
|
|
508
508
|
TZDataActivatedRule.new(self, year)
|
|
509
509
|
else
|
|
510
510
|
nil
|
|
511
511
|
end
|
|
512
512
|
end
|
|
513
|
-
|
|
513
|
+
|
|
514
514
|
def at_utc_time(year, utc_offset, std_offset)
|
|
515
515
|
@at_time.to_utc(utc_offset, std_offset,
|
|
516
516
|
year, @in_month, @on_day.to_absolute(year, @in_month))
|
|
517
517
|
end
|
|
518
|
-
|
|
518
|
+
|
|
519
519
|
private
|
|
520
520
|
def parse_from(from)
|
|
521
521
|
lower = from.downcase
|
|
@@ -527,7 +527,7 @@ module TZInfo
|
|
|
527
527
|
raise "Invalid from: #{from}"
|
|
528
528
|
end
|
|
529
529
|
end
|
|
530
|
-
|
|
530
|
+
|
|
531
531
|
def parse_to(to)
|
|
532
532
|
lower = to.downcase
|
|
533
533
|
if lower =~ /^max/
|
|
@@ -540,12 +540,12 @@ module TZInfo
|
|
|
540
540
|
raise "Invalid to: #{to}"
|
|
541
541
|
end
|
|
542
542
|
end
|
|
543
|
-
|
|
543
|
+
|
|
544
544
|
def parse_type(type)
|
|
545
545
|
raise "Unsupported rule type: #{type}" if type != '-'
|
|
546
546
|
nil
|
|
547
|
-
end
|
|
548
|
-
|
|
547
|
+
end
|
|
548
|
+
|
|
549
549
|
def parse_letter(letter)
|
|
550
550
|
if letter == '-'
|
|
551
551
|
nil
|
|
@@ -554,40 +554,40 @@ module TZInfo
|
|
|
554
554
|
end
|
|
555
555
|
end
|
|
556
556
|
end
|
|
557
|
-
|
|
557
|
+
|
|
558
558
|
# Base class for Zones and Links.
|
|
559
559
|
#
|
|
560
560
|
# @private
|
|
561
561
|
class TZDataDefinition #:nodoc:
|
|
562
562
|
include TZDataParserUtils
|
|
563
|
-
|
|
563
|
+
|
|
564
564
|
attr_reader :name
|
|
565
565
|
attr_reader :name_elements
|
|
566
566
|
attr_reader :path_elements
|
|
567
|
-
|
|
567
|
+
|
|
568
568
|
def initialize(name)
|
|
569
569
|
@name = name
|
|
570
|
-
|
|
570
|
+
|
|
571
571
|
# + and - aren't allowed in class names
|
|
572
572
|
@name_elements = name.gsub(/-/, '__m__').gsub(/\+/, '__p__').split(/\//)
|
|
573
573
|
@path_elements = @name_elements.clone
|
|
574
574
|
@path_elements.pop
|
|
575
|
-
end
|
|
576
|
-
|
|
575
|
+
end
|
|
576
|
+
|
|
577
577
|
# Creates necessary directories, the file, writes the class header and footer
|
|
578
|
-
# and yields to a block to write the content.
|
|
579
|
-
def create_file(output_dir)
|
|
578
|
+
# and yields to a block to write the content.
|
|
579
|
+
def create_file(output_dir)
|
|
580
580
|
dir = File.join(output_dir, 'definitions', @path_elements.join(File::SEPARATOR))
|
|
581
581
|
FileUtils.mkdir_p(dir)
|
|
582
|
-
|
|
582
|
+
|
|
583
583
|
open_file(File.join(output_dir, 'definitions', @name_elements.join(File::SEPARATOR)) + '.rb', 'w', :external_encoding => 'UTF-8', :universal_newline => true) do |file|
|
|
584
584
|
|
|
585
585
|
file.instance_variable_set(:@tz_indent, 0)
|
|
586
|
-
|
|
586
|
+
|
|
587
587
|
def file.indent(by)
|
|
588
588
|
@tz_indent += by
|
|
589
589
|
end
|
|
590
|
-
|
|
590
|
+
|
|
591
591
|
def file.puts(s)
|
|
592
592
|
super("#{' ' * @tz_indent}#{s}")
|
|
593
593
|
end
|
|
@@ -602,21 +602,21 @@ module TZInfo
|
|
|
602
602
|
file.puts('module Data')
|
|
603
603
|
file.indent(2)
|
|
604
604
|
file.puts('module Definitions')
|
|
605
|
-
file.indent(2)
|
|
606
|
-
|
|
607
|
-
@name_elements.each do |part|
|
|
605
|
+
file.indent(2)
|
|
606
|
+
|
|
607
|
+
@name_elements.each do |part|
|
|
608
608
|
file.puts("module #{part}")
|
|
609
609
|
file.indent(2)
|
|
610
610
|
end
|
|
611
|
-
|
|
611
|
+
|
|
612
612
|
file.puts('include TimezoneDefinition')
|
|
613
613
|
file.puts('')
|
|
614
|
-
|
|
614
|
+
|
|
615
615
|
yield file
|
|
616
|
-
|
|
616
|
+
|
|
617
617
|
@name_elements.each do
|
|
618
|
-
file.indent(-2)
|
|
619
|
-
file.puts('end')
|
|
618
|
+
file.indent(-2)
|
|
619
|
+
file.puts('end')
|
|
620
620
|
end
|
|
621
621
|
file.indent(-2)
|
|
622
622
|
file.puts('end') # end module Definitions
|
|
@@ -625,88 +625,88 @@ module TZInfo
|
|
|
625
625
|
file.indent(-2)
|
|
626
626
|
file.puts('end') # end module TZInfo
|
|
627
627
|
end
|
|
628
|
-
end
|
|
628
|
+
end
|
|
629
629
|
end
|
|
630
|
-
|
|
630
|
+
|
|
631
631
|
# A tz data Link.
|
|
632
632
|
#
|
|
633
633
|
# @private
|
|
634
634
|
class TZDataLink < TZDataDefinition #:nodoc:
|
|
635
635
|
include TZDataParserUtils
|
|
636
|
-
|
|
636
|
+
|
|
637
637
|
attr_reader :link_to
|
|
638
|
-
|
|
638
|
+
|
|
639
639
|
def initialize(name, link_to)
|
|
640
640
|
super(name)
|
|
641
641
|
@link_to = link_to
|
|
642
642
|
end
|
|
643
|
-
|
|
643
|
+
|
|
644
644
|
# Writes a module for this link.
|
|
645
645
|
def write_module(output_dir)
|
|
646
646
|
puts "writing link #{name}"
|
|
647
|
-
|
|
647
|
+
|
|
648
648
|
create_file(output_dir) {|file|
|
|
649
|
-
file.puts("linked_timezone #{quote_str(@name)}, #{quote_str(@link_to.name)}")
|
|
649
|
+
file.puts("linked_timezone #{quote_str(@name)}, #{quote_str(@link_to.name)}")
|
|
650
650
|
}
|
|
651
651
|
end
|
|
652
|
-
|
|
653
|
-
# Writes an index record for this link.
|
|
652
|
+
|
|
653
|
+
# Writes an index record for this link.
|
|
654
654
|
def write_index_record(file)
|
|
655
655
|
file.puts(" linked_timezone #{quote_str(@name)}")
|
|
656
656
|
end
|
|
657
657
|
end
|
|
658
|
-
|
|
658
|
+
|
|
659
659
|
# A tz data Zone. Each line from the tz data is loaded as a TZDataObservance.
|
|
660
660
|
#
|
|
661
661
|
# @private
|
|
662
662
|
class TZDataZone < TZDataDefinition #:nodoc:
|
|
663
663
|
include TZDataParserUtils
|
|
664
|
-
|
|
664
|
+
|
|
665
665
|
attr_reader :observances
|
|
666
|
-
|
|
666
|
+
|
|
667
667
|
def initialize(name, years)
|
|
668
668
|
super(name)
|
|
669
669
|
@years = years
|
|
670
670
|
@observances = []
|
|
671
671
|
end
|
|
672
|
-
|
|
673
|
-
def add_observance(observance)
|
|
672
|
+
|
|
673
|
+
def add_observance(observance)
|
|
674
674
|
@observances << observance
|
|
675
|
-
end
|
|
676
|
-
|
|
675
|
+
end
|
|
676
|
+
|
|
677
677
|
# Writes the module for the zone. Iterates all the periods and asks them
|
|
678
678
|
# to write all periods in the timezone.
|
|
679
|
-
def write_module(output_dir)
|
|
679
|
+
def write_module(output_dir)
|
|
680
680
|
puts "writing zone #{name}"
|
|
681
|
-
|
|
682
|
-
create_file(output_dir) {|file|
|
|
683
|
-
|
|
681
|
+
|
|
682
|
+
create_file(output_dir) {|file|
|
|
683
|
+
|
|
684
684
|
file.puts("timezone #{quote_str(@name)} do |tz|")
|
|
685
685
|
file.indent(2)
|
|
686
|
-
|
|
686
|
+
|
|
687
687
|
transitions = find_transitions
|
|
688
688
|
transitions.output_module(file)
|
|
689
|
-
|
|
689
|
+
|
|
690
690
|
file.indent(-2)
|
|
691
691
|
file.puts('end')
|
|
692
|
-
}
|
|
692
|
+
}
|
|
693
693
|
end
|
|
694
|
-
|
|
695
|
-
# Writes an index record for this zone.
|
|
694
|
+
|
|
695
|
+
# Writes an index record for this zone.
|
|
696
696
|
def write_index_record(file)
|
|
697
697
|
file.puts(" timezone #{quote_str(@name)}")
|
|
698
698
|
end
|
|
699
|
-
|
|
699
|
+
|
|
700
700
|
private
|
|
701
701
|
def find_transitions
|
|
702
702
|
transitions = TZDataTransitions.new(@years)
|
|
703
|
-
|
|
703
|
+
|
|
704
704
|
# algorithm from zic.c outzone
|
|
705
|
-
|
|
705
|
+
|
|
706
706
|
start_time = nil
|
|
707
707
|
until_time = nil
|
|
708
|
-
|
|
709
|
-
|
|
708
|
+
|
|
709
|
+
|
|
710
710
|
@observances.each_with_index {|observance, i|
|
|
711
711
|
std_offset = 0
|
|
712
712
|
use_start = i > 0
|
|
@@ -715,11 +715,11 @@ module TZInfo
|
|
|
715
715
|
start_zone_id = nil
|
|
716
716
|
start_utc_offset = observance.utc_offset
|
|
717
717
|
start_std_offset = 0
|
|
718
|
-
|
|
718
|
+
|
|
719
719
|
if observance.rule_set.count == 0
|
|
720
720
|
std_offset = observance.std_offset
|
|
721
721
|
start_zone_id = observance.format.expand(utc_offset, std_offset, nil)
|
|
722
|
-
|
|
722
|
+
|
|
723
723
|
if use_start
|
|
724
724
|
transitions << TZDataTransition.new(start_time, utc_offset, std_offset, start_zone_id)
|
|
725
725
|
use_start = false
|
|
@@ -727,38 +727,38 @@ module TZInfo
|
|
|
727
727
|
# zic algorithm only outputs this if std_offset is non-zero
|
|
728
728
|
# to get the initial LMT range, we output this regardless
|
|
729
729
|
transitions << TZDataTransition.new(nil, utc_offset, std_offset, start_zone_id)
|
|
730
|
-
end
|
|
730
|
+
end
|
|
731
731
|
else
|
|
732
732
|
@years.each {|year|
|
|
733
733
|
if use_until && year > observance.valid_until.year
|
|
734
734
|
break
|
|
735
735
|
end
|
|
736
|
-
|
|
736
|
+
|
|
737
737
|
activated_rules = []
|
|
738
|
-
|
|
738
|
+
|
|
739
739
|
observance.rule_set.each {|rule|
|
|
740
740
|
activated_rule = rule.activate(year)
|
|
741
741
|
activated_rules << activated_rule unless activated_rule.nil?
|
|
742
742
|
}
|
|
743
|
-
|
|
744
|
-
while true
|
|
743
|
+
|
|
744
|
+
while true
|
|
745
745
|
# turn until_time into UTC using the current utc_offset and std_offset
|
|
746
746
|
until_time = observance.valid_until.to_utc(utc_offset, std_offset) if use_until
|
|
747
|
-
|
|
747
|
+
|
|
748
748
|
earliest = nil
|
|
749
749
|
|
|
750
|
-
activated_rules.each {|activated_rule|
|
|
750
|
+
activated_rules.each {|activated_rule|
|
|
751
751
|
# recalculate the time using the current std_offset
|
|
752
|
-
activated_rule.calculate_time(utc_offset, std_offset)
|
|
753
|
-
earliest = activated_rule if earliest.nil? || activated_rule.at < earliest.at
|
|
752
|
+
activated_rule.calculate_time(utc_offset, std_offset)
|
|
753
|
+
earliest = activated_rule if earliest.nil? || activated_rule.at < earliest.at
|
|
754
754
|
}
|
|
755
|
-
|
|
756
|
-
break if earliest.nil?
|
|
757
|
-
activated_rules.delete(earliest)
|
|
758
|
-
break if use_until && earliest.at >= until_time
|
|
759
|
-
std_offset = earliest.rule.save
|
|
755
|
+
|
|
756
|
+
break if earliest.nil?
|
|
757
|
+
activated_rules.delete(earliest)
|
|
758
|
+
break if use_until && earliest.at >= until_time
|
|
759
|
+
std_offset = earliest.rule.save
|
|
760
760
|
use_start = false if use_start && earliest.at == start_time
|
|
761
|
-
|
|
761
|
+
|
|
762
762
|
if use_start
|
|
763
763
|
if earliest.at < start_time
|
|
764
764
|
start_utc_offset = observance.utc_offset
|
|
@@ -766,49 +766,49 @@ module TZInfo
|
|
|
766
766
|
start_zone_id = observance.format.expand(start_utc_offset, earliest.rule.save, earliest.rule.letter)
|
|
767
767
|
next
|
|
768
768
|
end
|
|
769
|
-
|
|
769
|
+
|
|
770
770
|
if start_zone_id.nil? && start_utc_offset + start_std_offset == observance.utc_offset + std_offset
|
|
771
771
|
start_zone_id = observance.format.expand(start_utc_offset, earliest.rule.save, earliest.rule.letter)
|
|
772
772
|
end
|
|
773
773
|
end
|
|
774
|
-
|
|
774
|
+
|
|
775
775
|
zone_id = observance.format.expand(observance.utc_offset, earliest.rule.save, earliest.rule.letter)
|
|
776
776
|
transitions << TZDataTransition.new(earliest.at, observance.utc_offset, earliest.rule.save, zone_id)
|
|
777
|
-
end
|
|
777
|
+
end
|
|
778
778
|
}
|
|
779
779
|
end
|
|
780
|
-
|
|
780
|
+
|
|
781
781
|
if use_start
|
|
782
782
|
start_zone_id = observance.format.expand(nil, nil, nil) if start_zone_id.nil? && observance.format.fixed?
|
|
783
|
-
raise 'Could not determine time zone abbreviation to use just after until time' if start_zone_id.nil?
|
|
783
|
+
raise 'Could not determine time zone abbreviation to use just after until time' if start_zone_id.nil?
|
|
784
784
|
transitions << TZDataTransition.new(start_time, start_utc_offset, start_std_offset, start_zone_id)
|
|
785
785
|
end
|
|
786
|
-
|
|
787
|
-
start_time = observance.valid_until.to_utc(utc_offset, std_offset) if use_until
|
|
786
|
+
|
|
787
|
+
start_time = observance.valid_until.to_utc(utc_offset, std_offset) if use_until
|
|
788
788
|
}
|
|
789
|
-
|
|
789
|
+
|
|
790
790
|
transitions
|
|
791
791
|
end
|
|
792
792
|
end
|
|
793
|
-
|
|
793
|
+
|
|
794
794
|
# A observance within a zone (a line within the zone definition).
|
|
795
795
|
#
|
|
796
796
|
# @private
|
|
797
797
|
class TZDataObservance #:nodoc:
|
|
798
798
|
include TZDataParserUtils
|
|
799
|
-
|
|
799
|
+
|
|
800
800
|
attr_reader :utc_offset
|
|
801
801
|
attr_reader :rule_set
|
|
802
802
|
attr_reader :format
|
|
803
803
|
attr_reader :valid_until
|
|
804
|
-
|
|
804
|
+
|
|
805
805
|
def initialize(utc_offset, rule_set, format, valid_until)
|
|
806
806
|
@utc_offset = parse_offset(utc_offset)
|
|
807
|
-
@rule_set = rule_set
|
|
807
|
+
@rule_set = rule_set
|
|
808
808
|
@format = TZDataFormat.new(format)
|
|
809
|
-
@valid_until = valid_until.nil? ? nil : TZDataUntil.new(valid_until)
|
|
810
|
-
end
|
|
811
|
-
|
|
809
|
+
@valid_until = valid_until.nil? ? nil : TZDataUntil.new(valid_until)
|
|
810
|
+
end
|
|
811
|
+
|
|
812
812
|
def std_offset
|
|
813
813
|
if @rule_set.kind_of?(TZDataFixedOffsetRules)
|
|
814
814
|
@rule_set.offset
|
|
@@ -817,159 +817,159 @@ module TZInfo
|
|
|
817
817
|
end
|
|
818
818
|
end
|
|
819
819
|
end
|
|
820
|
-
|
|
820
|
+
|
|
821
821
|
# Collection of TZDataTransition instances used when building a zone class.
|
|
822
822
|
#
|
|
823
823
|
# @private
|
|
824
824
|
class TZDataTransitions #:nodoc:
|
|
825
825
|
include TZDataParserUtils
|
|
826
|
-
|
|
826
|
+
|
|
827
827
|
def initialize(years)
|
|
828
828
|
@years = years
|
|
829
829
|
@transitions = []
|
|
830
830
|
end
|
|
831
|
-
|
|
831
|
+
|
|
832
832
|
def << (transition)
|
|
833
833
|
@transitions << transition
|
|
834
|
-
end
|
|
835
|
-
|
|
834
|
+
end
|
|
835
|
+
|
|
836
836
|
def output_module(file)
|
|
837
837
|
optimize
|
|
838
|
-
|
|
838
|
+
|
|
839
839
|
# Try and end on a transition to std if one happens in the last year.
|
|
840
|
-
if @transitions.length > 1 &&
|
|
840
|
+
if @transitions.length > 1 &&
|
|
841
841
|
@transitions.last.std_offset != 0 &&
|
|
842
842
|
@transitions[@transitions.length - 2].std_offset == 0 &&
|
|
843
843
|
@transitions[@transitions.length - 2].at_utc.year == @years.max
|
|
844
|
-
|
|
844
|
+
|
|
845
845
|
transitions = @transitions[0..@transitions.length - 2]
|
|
846
846
|
else
|
|
847
847
|
transitions = @transitions
|
|
848
848
|
end
|
|
849
|
-
|
|
849
|
+
|
|
850
850
|
process_offsets(file)
|
|
851
851
|
file.puts('')
|
|
852
|
-
|
|
853
|
-
transitions.each do |t|
|
|
852
|
+
|
|
853
|
+
transitions.each do |t|
|
|
854
854
|
t.write(file)
|
|
855
|
-
end
|
|
855
|
+
end
|
|
856
856
|
end
|
|
857
|
-
|
|
857
|
+
|
|
858
858
|
private
|
|
859
859
|
def optimize
|
|
860
860
|
@transitions.sort!
|
|
861
|
-
|
|
861
|
+
|
|
862
862
|
# Optimization logic from zic.c writezone.
|
|
863
|
-
|
|
863
|
+
|
|
864
864
|
from_i = 0
|
|
865
865
|
to_i = 0
|
|
866
|
-
|
|
866
|
+
|
|
867
867
|
while from_i < @transitions.length
|
|
868
|
-
if to_i > 1 &&
|
|
868
|
+
if to_i > 1 &&
|
|
869
869
|
!@transitions[from_i].at_utc.nil? &&
|
|
870
870
|
!@transitions[to_i - 1].at_utc.nil? &&
|
|
871
871
|
@transitions[from_i].at_utc + Rational(@transitions[to_i - 1].total_offset, 86400) <=
|
|
872
872
|
@transitions[to_i - 1].at_utc + Rational(@transitions[to_i - 2].total_offset, 86400)
|
|
873
|
-
|
|
874
|
-
@transitions[to_i - 1] = @transitions[from_i].clone_with_at(@transitions[to_i - 1].at_utc)
|
|
873
|
+
|
|
874
|
+
@transitions[to_i - 1] = @transitions[from_i].clone_with_at(@transitions[to_i - 1].at_utc)
|
|
875
875
|
from_i += 1
|
|
876
876
|
next
|
|
877
877
|
end
|
|
878
|
-
|
|
879
|
-
# Shuffle transitions up, eliminating any redundant transitions
|
|
878
|
+
|
|
879
|
+
# Shuffle transitions up, eliminating any redundant transitions
|
|
880
880
|
# along the way.
|
|
881
881
|
if to_i == 0 ||
|
|
882
882
|
@transitions[to_i - 1].utc_offset != @transitions[from_i].utc_offset ||
|
|
883
883
|
@transitions[to_i - 1].std_offset != @transitions[from_i].std_offset ||
|
|
884
884
|
@transitions[to_i - 1].zone_id != @transitions[from_i].zone_id
|
|
885
|
-
|
|
885
|
+
|
|
886
886
|
@transitions[to_i] = @transitions[from_i]
|
|
887
|
-
to_i += 1
|
|
887
|
+
to_i += 1
|
|
888
888
|
end
|
|
889
|
-
|
|
889
|
+
|
|
890
890
|
from_i += 1
|
|
891
|
-
end
|
|
892
|
-
|
|
891
|
+
end
|
|
892
|
+
|
|
893
893
|
if to_i > 0
|
|
894
894
|
@transitions = @transitions[0..to_i - 1]
|
|
895
895
|
else
|
|
896
896
|
@transitions = []
|
|
897
|
-
end
|
|
897
|
+
end
|
|
898
898
|
end
|
|
899
|
-
|
|
900
|
-
def quote_zone_id(zone_id)
|
|
899
|
+
|
|
900
|
+
def quote_zone_id(zone_id)
|
|
901
901
|
if zone_id =~ %r{[\-+']}
|
|
902
|
-
":#{quote_str(zone_id)}"
|
|
902
|
+
":#{quote_str(zone_id)}"
|
|
903
903
|
else
|
|
904
904
|
":#{zone_id}"
|
|
905
905
|
end
|
|
906
|
-
end
|
|
907
|
-
|
|
906
|
+
end
|
|
907
|
+
|
|
908
908
|
def process_offsets(file)
|
|
909
909
|
# A bit of a hack at the moment. The offset used to be output with
|
|
910
910
|
# each period (pair of transitions). They are now separated from the
|
|
911
911
|
# transition data. The code should probably be changed at some point to
|
|
912
|
-
# setup the offsets at an earlier stage.
|
|
913
|
-
|
|
912
|
+
# setup the offsets at an earlier stage.
|
|
913
|
+
|
|
914
914
|
# Assume that when this is called, the first transition is the Local
|
|
915
915
|
# Mean Time initial rule or a transition with no time that defines the
|
|
916
916
|
# offset for the entire zone.
|
|
917
|
-
|
|
917
|
+
|
|
918
918
|
offsets = []
|
|
919
|
-
|
|
919
|
+
|
|
920
920
|
# Find the first std offset. Timezones always start in std.
|
|
921
921
|
@transitions.each do |t|
|
|
922
922
|
if t.std_offset == 0
|
|
923
|
-
offset = {:utc_offset => t.utc_offset,
|
|
923
|
+
offset = {:utc_offset => t.utc_offset,
|
|
924
924
|
:std_offset => t.std_offset,
|
|
925
925
|
:zone_id => t.zone_id,
|
|
926
926
|
:name => 'o0'}
|
|
927
|
-
|
|
927
|
+
|
|
928
928
|
offsets << offset
|
|
929
929
|
break
|
|
930
930
|
end
|
|
931
931
|
end
|
|
932
|
-
|
|
932
|
+
|
|
933
933
|
@transitions.each do |t|
|
|
934
|
-
offset = offsets.find do |o|
|
|
934
|
+
offset = offsets.find do |o|
|
|
935
935
|
o[:utc_offset] == t.utc_offset &&
|
|
936
936
|
o[:std_offset] == t.std_offset &&
|
|
937
937
|
o[:zone_id] == t.zone_id
|
|
938
938
|
end
|
|
939
|
-
|
|
939
|
+
|
|
940
940
|
unless offset
|
|
941
|
-
offset = {:utc_offset => t.utc_offset,
|
|
941
|
+
offset = {:utc_offset => t.utc_offset,
|
|
942
942
|
:std_offset => t.std_offset,
|
|
943
943
|
:zone_id => t.zone_id,
|
|
944
944
|
:name => "o#{offsets.length}"}
|
|
945
|
-
|
|
945
|
+
|
|
946
946
|
offsets << offset
|
|
947
947
|
end
|
|
948
|
-
|
|
948
|
+
|
|
949
949
|
t.offset_name = offset[:name]
|
|
950
950
|
end
|
|
951
|
-
|
|
951
|
+
|
|
952
952
|
offsets.each do |offset|
|
|
953
953
|
file.puts("tz.offset :#{offset[:name]}, #{offset[:utc_offset]}, #{offset[:std_offset]}, #{quote_zone_id(offset[:zone_id])}")
|
|
954
954
|
end
|
|
955
|
-
|
|
955
|
+
|
|
956
956
|
end
|
|
957
957
|
end
|
|
958
|
-
|
|
958
|
+
|
|
959
959
|
# A transition that will be used to write the periods in a zone class.
|
|
960
960
|
#
|
|
961
961
|
# @private
|
|
962
962
|
class TZDataTransition #:nodoc:
|
|
963
963
|
include Comparable
|
|
964
|
-
|
|
964
|
+
|
|
965
965
|
EPOCH = DateTime.new(1970, 1, 1)
|
|
966
|
-
|
|
966
|
+
|
|
967
967
|
attr_reader :at_utc
|
|
968
968
|
attr_reader :utc_offset
|
|
969
969
|
attr_reader :std_offset
|
|
970
970
|
attr_reader :zone_id
|
|
971
971
|
attr_accessor :offset_name
|
|
972
|
-
|
|
972
|
+
|
|
973
973
|
def initialize(at_utc, utc_offset, std_offset, zone_id)
|
|
974
974
|
@at_utc = at_utc
|
|
975
975
|
@utc_offset = utc_offset
|
|
@@ -977,11 +977,11 @@ module TZInfo
|
|
|
977
977
|
@zone_id = zone_id
|
|
978
978
|
@offset_name = nil
|
|
979
979
|
end
|
|
980
|
-
|
|
980
|
+
|
|
981
981
|
def to_s
|
|
982
982
|
"At #{at_utc} UTC switch to UTC offset #{@utc_offset} with std offset #{@std_offset}, zone id #{@zone_id}"
|
|
983
983
|
end
|
|
984
|
-
|
|
984
|
+
|
|
985
985
|
def <=>(transition)
|
|
986
986
|
if @at_utc == transition.at_utc
|
|
987
987
|
0
|
|
@@ -989,29 +989,29 @@ module TZInfo
|
|
|
989
989
|
-1
|
|
990
990
|
elsif transition.nil?
|
|
991
991
|
1
|
|
992
|
-
else
|
|
992
|
+
else
|
|
993
993
|
@at_utc - transition.at_utc
|
|
994
994
|
end
|
|
995
995
|
end
|
|
996
|
-
|
|
996
|
+
|
|
997
997
|
def total_offset
|
|
998
998
|
@utc_offset + @std_offset
|
|
999
999
|
end
|
|
1000
|
-
|
|
1000
|
+
|
|
1001
1001
|
def clone_with_at(at_utc)
|
|
1002
1002
|
TZDataTransition.new(at_utc, @utc_offset, @std_offset, @zone_id)
|
|
1003
1003
|
end
|
|
1004
|
-
|
|
1005
|
-
def write(file)
|
|
1004
|
+
|
|
1005
|
+
def write(file)
|
|
1006
1006
|
if @at_utc
|
|
1007
|
-
file.puts "tz.transition #{@at_utc.year}, #{@at_utc.mon}, :#{@offset_name}, #{timestamp_parameters(@at_utc)}"
|
|
1008
|
-
end
|
|
1007
|
+
file.puts "tz.transition #{@at_utc.year}, #{@at_utc.mon}, :#{@offset_name}, #{timestamp_parameters(@at_utc)}"
|
|
1008
|
+
end
|
|
1009
1009
|
end
|
|
1010
|
-
|
|
1010
|
+
|
|
1011
1011
|
private
|
|
1012
1012
|
def timestamp_parameters(datetime)
|
|
1013
1013
|
timestamp = ((datetime - EPOCH) * 86400).to_i
|
|
1014
|
-
|
|
1014
|
+
|
|
1015
1015
|
if timestamp < 0 || timestamp > 2147483647
|
|
1016
1016
|
# Output DateTime parameters as well as a timestamp for platforms
|
|
1017
1017
|
# where Time doesn't support negative or 64-bit values.
|
|
@@ -1021,7 +1021,7 @@ module TZInfo
|
|
|
1021
1021
|
end
|
|
1022
1022
|
end
|
|
1023
1023
|
end
|
|
1024
|
-
|
|
1024
|
+
|
|
1025
1025
|
# An instance of a rule for a year.
|
|
1026
1026
|
#
|
|
1027
1027
|
# @private
|
|
@@ -1029,18 +1029,18 @@ module TZInfo
|
|
|
1029
1029
|
attr_reader :rule
|
|
1030
1030
|
attr_reader :year
|
|
1031
1031
|
attr_reader :at
|
|
1032
|
-
|
|
1032
|
+
|
|
1033
1033
|
def initialize(rule, year)
|
|
1034
1034
|
@rule = rule
|
|
1035
1035
|
@year = year
|
|
1036
1036
|
@at = nil
|
|
1037
1037
|
end
|
|
1038
|
-
|
|
1038
|
+
|
|
1039
1039
|
def calculate_time(utc_offset, std_offset)
|
|
1040
1040
|
@at = @rule.at_utc_time(@year, utc_offset, std_offset)
|
|
1041
1041
|
end
|
|
1042
1042
|
end
|
|
1043
|
-
|
|
1043
|
+
|
|
1044
1044
|
# A tz data time definition - a sign (1 or -1), hour, minute, second and
|
|
1045
1045
|
# reference (:utc, :standard or :wall_clock).
|
|
1046
1046
|
#
|
|
@@ -1051,15 +1051,15 @@ module TZInfo
|
|
|
1051
1051
|
attr_reader :minute
|
|
1052
1052
|
attr_reader :second
|
|
1053
1053
|
attr_reader :ref
|
|
1054
|
-
|
|
1054
|
+
|
|
1055
1055
|
def initialize(spec)
|
|
1056
1056
|
raise "Invalid time: #{spec}" if spec !~ /^(-?)([0-9]+)(:([0-9]+)(:([0-9]+))?)?([wguzs])?$/
|
|
1057
|
-
|
|
1057
|
+
|
|
1058
1058
|
@sign = $1 == '-' ? -1 : 1
|
|
1059
1059
|
@hour = $2.to_i
|
|
1060
1060
|
@minute = $4.nil? ? 0 : $4.to_i
|
|
1061
1061
|
@second = $6.nil? ? 0 : $6.to_i
|
|
1062
|
-
|
|
1062
|
+
|
|
1063
1063
|
if $7 == 's'
|
|
1064
1064
|
@ref = :standard
|
|
1065
1065
|
elsif $7 == 'g' || $7 == 'u' || $7 == 'z'
|
|
@@ -1068,9 +1068,9 @@ module TZInfo
|
|
|
1068
1068
|
@ref = :wall_clock
|
|
1069
1069
|
end
|
|
1070
1070
|
end
|
|
1071
|
-
|
|
1071
|
+
|
|
1072
1072
|
# Converts the time to UTC given a utc_offset and std_offset.
|
|
1073
|
-
def to_utc(utc_offset, std_offset, year, month, day)
|
|
1073
|
+
def to_utc(utc_offset, std_offset, year, month, day)
|
|
1074
1074
|
result = if @hour > 24 || @hour == 24 && (@minute > 0 || @second > 0) || @sign != 1
|
|
1075
1075
|
DateTime.new(year, month, day, 0, 0, 0) + Rational(@sign * (@second + (@minute + @hour * 60) * 60), 86400)
|
|
1076
1076
|
else
|
|
@@ -1078,12 +1078,12 @@ module TZInfo
|
|
|
1078
1078
|
end
|
|
1079
1079
|
|
|
1080
1080
|
offset = 0
|
|
1081
|
-
offset = offset + utc_offset if @ref == :standard || @ref == :wall_clock
|
|
1082
|
-
offset = offset + std_offset if @ref == :wall_clock
|
|
1083
|
-
result - Rational(offset, 86400)
|
|
1081
|
+
offset = offset + utc_offset if @ref == :standard || @ref == :wall_clock
|
|
1082
|
+
offset = offset + std_offset if @ref == :wall_clock
|
|
1083
|
+
result - Rational(offset, 86400)
|
|
1084
1084
|
end
|
|
1085
1085
|
end
|
|
1086
|
-
|
|
1086
|
+
|
|
1087
1087
|
# A tz data day of the month reference. Can either be an absolute day,
|
|
1088
1088
|
# a last week day or a week day >= or <= than a specific day of month.
|
|
1089
1089
|
#
|
|
@@ -1093,10 +1093,10 @@ module TZInfo
|
|
|
1093
1093
|
attr_reader :day_of_month
|
|
1094
1094
|
attr_reader :day_of_week
|
|
1095
1095
|
attr_reader :operator
|
|
1096
|
-
|
|
1096
|
+
|
|
1097
1097
|
def initialize(spec)
|
|
1098
1098
|
raise "Invalid on: #{spec}" if spec !~ /^([0-9]+)|(last([A-Za-z]+))|(([A-Za-z]+)([<>]=)([0-9]+))$/
|
|
1099
|
-
|
|
1099
|
+
|
|
1100
1100
|
if $1
|
|
1101
1101
|
@type = :absolute
|
|
1102
1102
|
@day_of_month = $1.to_i
|
|
@@ -1110,21 +1110,21 @@ module TZInfo
|
|
|
1110
1110
|
@day_of_month = $7.to_i
|
|
1111
1111
|
end
|
|
1112
1112
|
end
|
|
1113
|
-
|
|
1113
|
+
|
|
1114
1114
|
# Returns the absolute day of month for the given year and month.
|
|
1115
1115
|
def to_absolute(year, month)
|
|
1116
1116
|
case @type
|
|
1117
1117
|
when :last
|
|
1118
|
-
last_day_in_month = (Date.new(year, month, 1) >> 1) - 1
|
|
1118
|
+
last_day_in_month = (Date.new(year, month, 1) >> 1) - 1
|
|
1119
1119
|
offset = last_day_in_month.wday - @day_of_week
|
|
1120
1120
|
offset = offset + 7 if offset < 0
|
|
1121
1121
|
(last_day_in_month - offset).day
|
|
1122
1122
|
when :comparison
|
|
1123
|
-
pivot = Date.new(year, month, @day_of_month)
|
|
1123
|
+
pivot = Date.new(year, month, @day_of_month)
|
|
1124
1124
|
offset = @day_of_week - pivot.wday
|
|
1125
1125
|
offset = -offset if @operator == :less_equal
|
|
1126
1126
|
offset = offset + 7 if offset < 0
|
|
1127
|
-
offset = -offset if @operator == :less_equal
|
|
1127
|
+
offset = -offset if @operator == :less_equal
|
|
1128
1128
|
result = pivot + offset
|
|
1129
1129
|
if result.month != pivot.month
|
|
1130
1130
|
puts self.inspect
|
|
@@ -1132,12 +1132,12 @@ module TZInfo
|
|
|
1132
1132
|
puts month
|
|
1133
1133
|
end
|
|
1134
1134
|
raise 'No suitable date found' if result.month != pivot.month
|
|
1135
|
-
result.day
|
|
1135
|
+
result.day
|
|
1136
1136
|
else #absolute
|
|
1137
1137
|
@day_of_month
|
|
1138
1138
|
end
|
|
1139
1139
|
end
|
|
1140
|
-
|
|
1140
|
+
|
|
1141
1141
|
private
|
|
1142
1142
|
def parse_day_of_week(day_of_week)
|
|
1143
1143
|
lower = day_of_week.downcase
|
|
@@ -1159,7 +1159,7 @@ module TZInfo
|
|
|
1159
1159
|
raise "Invalid day of week: #{day_of_week}"
|
|
1160
1160
|
end
|
|
1161
1161
|
end
|
|
1162
|
-
|
|
1162
|
+
|
|
1163
1163
|
def parse_operator(operator)
|
|
1164
1164
|
if operator == '>='
|
|
1165
1165
|
:greater_equal
|
|
@@ -1169,40 +1169,40 @@ module TZInfo
|
|
|
1169
1169
|
raise "Invalid operator: #{operator}"
|
|
1170
1170
|
end
|
|
1171
1171
|
end
|
|
1172
|
-
end
|
|
1173
|
-
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
1174
|
# A tz data Zone until reference.
|
|
1175
1175
|
#
|
|
1176
1176
|
# @private
|
|
1177
1177
|
class TZDataUntil #:nodoc:
|
|
1178
1178
|
include TZDataParserUtils
|
|
1179
|
-
|
|
1179
|
+
|
|
1180
1180
|
attr_reader :year
|
|
1181
1181
|
attr_reader :month
|
|
1182
1182
|
attr_reader :day
|
|
1183
1183
|
attr_reader :time
|
|
1184
|
-
|
|
1185
|
-
def initialize(spec)
|
|
1186
|
-
parts = spec.split(/\s+/)
|
|
1184
|
+
|
|
1185
|
+
def initialize(spec)
|
|
1186
|
+
parts = spec.split(/\s+/)
|
|
1187
1187
|
raise "Invalid until: #{spec}" if parts.length < 1
|
|
1188
|
-
|
|
1188
|
+
|
|
1189
1189
|
@year = parts[0].to_i
|
|
1190
1190
|
@month = parts.length > 1 ? parse_month(parts[1]) : 1
|
|
1191
1191
|
@day = TZDataDayOfMonth.new(parts.length > 2 ? parts[2] : '1')
|
|
1192
1192
|
@time = TZDataTime.new(parts.length > 3 ? parts[3] : '00:00')
|
|
1193
1193
|
end
|
|
1194
|
-
|
|
1194
|
+
|
|
1195
1195
|
# Converts the reference to a UTC DateTime.
|
|
1196
1196
|
def to_utc(utc_offset, std_offset)
|
|
1197
|
-
@time.to_utc(utc_offset, std_offset, @year, @month, @day.to_absolute(@year, @month))
|
|
1197
|
+
@time.to_utc(utc_offset, std_offset, @year, @month, @day.to_absolute(@year, @month))
|
|
1198
1198
|
end
|
|
1199
1199
|
end
|
|
1200
|
-
|
|
1200
|
+
|
|
1201
1201
|
# A tz data Zone format string. Either alternate standard/daylight-savings,
|
|
1202
1202
|
# substitution (%s) format or a fixed string.
|
|
1203
1203
|
#
|
|
1204
1204
|
# @private
|
|
1205
|
-
class TZDataFormat #:nodoc:
|
|
1205
|
+
class TZDataFormat #:nodoc:
|
|
1206
1206
|
def initialize(spec)
|
|
1207
1207
|
if spec =~ /\A([^\/]*)\/(.*)\z/
|
|
1208
1208
|
@type = :alternate
|
|
@@ -1216,7 +1216,7 @@ module TZInfo
|
|
|
1216
1216
|
@abbrev = spec
|
|
1217
1217
|
end
|
|
1218
1218
|
end
|
|
1219
|
-
|
|
1219
|
+
|
|
1220
1220
|
# Expands given the base offset to UTC, the current daylight savings
|
|
1221
1221
|
# offset and rule string.
|
|
1222
1222
|
def expand(utc_offset, std_offset, rule_string)
|
|
@@ -1232,14 +1232,14 @@ module TZInfo
|
|
|
1232
1232
|
end
|
|
1233
1233
|
else
|
|
1234
1234
|
@abbrev
|
|
1235
|
-
end
|
|
1235
|
+
end
|
|
1236
1236
|
end
|
|
1237
|
-
|
|
1237
|
+
|
|
1238
1238
|
# True if the format requires substitutions (%s or %z).
|
|
1239
1239
|
def subst?
|
|
1240
1240
|
@type == :subst
|
|
1241
1241
|
end
|
|
1242
|
-
|
|
1242
|
+
|
|
1243
1243
|
# Is a fixed format string.
|
|
1244
1244
|
def fixed?
|
|
1245
1245
|
@type == :fixed
|
|
@@ -1277,67 +1277,67 @@ module TZInfo
|
|
|
1277
1277
|
end
|
|
1278
1278
|
end
|
|
1279
1279
|
end
|
|
1280
|
-
|
|
1280
|
+
|
|
1281
1281
|
# A location (latitude + longitude)
|
|
1282
1282
|
#
|
|
1283
1283
|
# @private
|
|
1284
1284
|
class TZDataLocation #:nodoc:
|
|
1285
1285
|
attr_reader :latitude
|
|
1286
1286
|
attr_reader :longitude
|
|
1287
|
-
|
|
1288
|
-
# Constructs a new TZDataLocation from a string in ISO 6709
|
|
1289
|
-
# sign-degrees-minutes-seconds format, either +-DDMM+-DDDMM
|
|
1290
|
-
# or +-DDMMSS+-DDDMMSS, first latitude (+ is north),
|
|
1287
|
+
|
|
1288
|
+
# Constructs a new TZDataLocation from a string in ISO 6709
|
|
1289
|
+
# sign-degrees-minutes-seconds format, either +-DDMM+-DDDMM
|
|
1290
|
+
# or +-DDMMSS+-DDDMMSS, first latitude (+ is north),
|
|
1291
1291
|
# then longitude (+ is east).
|
|
1292
1292
|
def initialize(coordinates)
|
|
1293
1293
|
if coordinates !~ /^([+\-])([0-9]{2})([0-9]{2})([0-9]{2})?([+\-])([0-9]{3})([0-9]{2})([0-9]{2})?$/
|
|
1294
1294
|
raise "Invalid coordinates: #{coordinates}"
|
|
1295
1295
|
end
|
|
1296
|
-
|
|
1296
|
+
|
|
1297
1297
|
@latitude = Rational($2.to_i) + Rational($3.to_i, 60)
|
|
1298
1298
|
@latitude += Rational($4.to_i, 3600) unless $4.nil?
|
|
1299
1299
|
@latitude = -@latitude if $1 == '-'
|
|
1300
|
-
|
|
1300
|
+
|
|
1301
1301
|
@longitude = Rational($6.to_i) + Rational($7.to_i, 60)
|
|
1302
1302
|
@longitude += Rational($8.to_i, 3600) unless $8.nil?
|
|
1303
1303
|
@longitude = -@longitude if $5 == '-'
|
|
1304
1304
|
end
|
|
1305
|
-
end
|
|
1305
|
+
end
|
|
1306
1306
|
|
|
1307
1307
|
# @private
|
|
1308
1308
|
TZDataCountryTimezone = Struct.new(:timezone, :description, :location) #:nodoc:
|
|
1309
|
-
|
|
1309
|
+
|
|
1310
1310
|
# An ISO 3166 country.
|
|
1311
1311
|
#
|
|
1312
1312
|
# @private
|
|
1313
1313
|
class TZDataCountry #:nodoc:
|
|
1314
1314
|
include TZDataParserUtils
|
|
1315
|
-
|
|
1315
|
+
|
|
1316
1316
|
attr_reader :code
|
|
1317
1317
|
attr_reader :name
|
|
1318
1318
|
attr_reader :zones
|
|
1319
|
-
|
|
1319
|
+
|
|
1320
1320
|
def initialize(code, name)
|
|
1321
1321
|
@code = code
|
|
1322
1322
|
@name = name
|
|
1323
1323
|
@zones = []
|
|
1324
1324
|
end
|
|
1325
|
-
|
|
1325
|
+
|
|
1326
1326
|
# Adds a TZDataCountryTimezone
|
|
1327
|
-
def add_zone(zone)
|
|
1328
|
-
@zones << zone
|
|
1329
|
-
end
|
|
1330
|
-
|
|
1327
|
+
def add_zone(zone)
|
|
1328
|
+
@zones << zone
|
|
1329
|
+
end
|
|
1330
|
+
|
|
1331
1331
|
def write_index_record(file)
|
|
1332
|
-
s = " country #{quote_str(@code)}, #{quote_str(@name)}"
|
|
1332
|
+
s = " country #{quote_str(@code)}, #{quote_str(@name)}"
|
|
1333
1333
|
s << ' do |c|' if @zones.length > 0
|
|
1334
|
-
|
|
1334
|
+
|
|
1335
1335
|
file.puts s
|
|
1336
|
-
|
|
1336
|
+
|
|
1337
1337
|
@zones.each do |zone|
|
|
1338
|
-
file.puts " c.timezone #{quote_str(zone.timezone.name)}, #{zone.location.latitude.numerator}, #{zone.location.latitude.denominator}, #{zone.location.longitude.numerator}, #{zone.location.longitude.denominator}#{zone.description.nil? ? '' : ', ' + quote_str(zone.description)}"
|
|
1338
|
+
file.puts " c.timezone #{quote_str(zone.timezone.name)}, #{zone.location.latitude.numerator}, #{zone.location.latitude.denominator}, #{zone.location.longitude.numerator}, #{zone.location.longitude.denominator}#{zone.description.nil? ? '' : ', ' + quote_str(zone.description)}"
|
|
1339
1339
|
end
|
|
1340
|
-
|
|
1340
|
+
|
|
1341
1341
|
file.puts ' end' if @zones.length > 0
|
|
1342
1342
|
end
|
|
1343
1343
|
end
|