timezone 1.3.2 → 1.3.30

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.
Files changed (285) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +15 -0
  3. data/.github/workflows/ci.yml +40 -0
  4. data/.rubocop.yml +24 -5
  5. data/CHANGES.markdown +115 -0
  6. data/CONTRIBUTING.markdown +10 -6
  7. data/README.markdown +5 -7
  8. data/Rakefile +3 -1
  9. data/benchmark.rb +16 -29
  10. data/data/Africa/Accra +1 -47
  11. data/data/Africa/Addis_Ababa +5 -4
  12. data/data/Africa/Algiers +2 -2
  13. data/data/Africa/Asmara +5 -4
  14. data/data/Africa/Asmera +5 -4
  15. data/data/Africa/Bangui +4 -1
  16. data/data/Africa/Blantyre +1 -1
  17. data/data/Africa/Brazzaville +4 -1
  18. data/data/Africa/Bujumbura +1 -1
  19. data/data/Africa/Cairo +32 -0
  20. data/data/Africa/Casablanca +43 -1
  21. data/data/Africa/Dar_es_Salaam +5 -4
  22. data/data/Africa/Djibouti +5 -4
  23. data/data/Africa/Douala +4 -1
  24. data/data/Africa/El_Aaiun +43 -1
  25. data/data/Africa/Gaborone +1 -1
  26. data/data/Africa/Harare +1 -1
  27. data/data/Africa/Juba +2 -1
  28. data/data/Africa/Kampala +5 -4
  29. data/data/Africa/Kigali +1 -1
  30. data/data/Africa/Kinshasa +4 -1
  31. data/data/Africa/Lagos +4 -1
  32. data/data/Africa/Libreville +4 -1
  33. data/data/Africa/Luanda +4 -1
  34. data/data/Africa/Lubumbashi +1 -1
  35. data/data/Africa/Lusaka +1 -1
  36. data/data/Africa/Malabo +4 -1
  37. data/data/Africa/Maputo +1 -1
  38. data/data/Africa/Mogadishu +5 -4
  39. data/data/Africa/Nairobi +5 -4
  40. data/data/Africa/Niamey +4 -1
  41. data/data/Africa/Porto-Novo +4 -1
  42. data/data/Africa/Sao_Tome +2 -1
  43. data/data/America/Anguilla +4 -1
  44. data/data/America/Antigua +4 -1
  45. data/data/America/Aruba +4 -2
  46. data/data/America/Asuncion +2 -29
  47. data/data/America/Atikokan +2 -7
  48. data/data/America/Bahia_Banderas +5 -39
  49. data/data/America/Barbados +8 -3
  50. data/data/America/Belize +44 -1
  51. data/data/America/Blanc-Sablon +3 -5
  52. data/data/America/Bogota +1 -1
  53. data/data/America/Cambridge_Bay +17 -3
  54. data/data/America/Campo_Grande +1 -40
  55. data/data/America/Cancun +7 -6
  56. data/data/America/Chihuahua +5 -37
  57. data/data/America/Ciudad_Juarez +94 -0
  58. data/data/America/Coral_Harbour +2 -7
  59. data/data/America/Coyhaique +134 -0
  60. data/data/America/Creston +11 -3
  61. data/data/America/Cuiaba +1 -40
  62. data/data/America/Curacao +4 -2
  63. data/data/America/Dawson +2 -38
  64. data/data/America/Detroit +5 -1
  65. data/data/America/Dominica +4 -1
  66. data/data/America/Edmonton +1 -5
  67. data/data/America/Ensenada +46 -8
  68. data/data/America/Godthab +31 -32
  69. data/data/America/Grand_Turk +1 -2
  70. data/data/America/Grenada +4 -1
  71. data/data/America/Guadeloupe +4 -1
  72. data/data/America/Guyana +4 -3
  73. data/data/America/Hermosillo +5 -7
  74. data/data/America/Indiana/Tell_City +9 -12
  75. data/data/America/Inuvik +17 -4
  76. data/data/America/Iqaluit +17 -3
  77. data/data/America/Kentucky/Louisville +4 -4
  78. data/data/America/Kralendijk +4 -2
  79. data/data/America/Louisville +4 -4
  80. data/data/America/Lower_Princes +4 -2
  81. data/data/America/Marigot +4 -1
  82. data/data/America/Matamoros +1 -1
  83. data/data/America/Mazatlan +5 -39
  84. data/data/America/Merida +3 -35
  85. data/data/America/Metlakatla +2 -1
  86. data/data/America/Mexico_City +4 -36
  87. data/data/America/Miquelon +2 -2
  88. data/data/America/Monterrey +6 -33
  89. data/data/America/Montreal +2 -2
  90. data/data/America/Montserrat +4 -1
  91. data/data/America/Nassau +86 -2
  92. data/data/America/Nipigon +103 -5
  93. data/data/America/Nuuk +119 -0
  94. data/data/America/Ojinaga +38 -38
  95. data/data/America/Pangnirtung +51 -38
  96. data/data/America/Port_of_Spain +4 -1
  97. data/data/America/Punta_Arenas +8 -7
  98. data/data/America/Rainy_River +118 -67
  99. data/data/America/Rankin_Inlet +17 -3
  100. data/data/America/Resolute +17 -3
  101. data/data/America/Santa_Isabel +46 -8
  102. data/data/America/Santiago +11 -11
  103. data/data/America/Sao_Paulo +1 -40
  104. data/data/America/Scoresbysund +30 -30
  105. data/data/America/St_Barthelemy +4 -1
  106. data/data/America/St_Kitts +4 -1
  107. data/data/America/St_Lucia +4 -1
  108. data/data/America/St_Thomas +4 -1
  109. data/data/America/St_Vincent +4 -1
  110. data/data/America/Thunder_Bay +99 -5
  111. data/data/America/Tijuana +46 -8
  112. data/data/America/Toronto +2 -2
  113. data/data/America/Tortola +4 -1
  114. data/data/America/Vancouver +2 -2
  115. data/data/America/Virgin +4 -1
  116. data/data/America/Whitehorse +4 -40
  117. data/data/America/Yellowknife +33 -5
  118. data/data/Antarctica/Casey +10 -0
  119. data/data/Antarctica/DumontDUrville +2 -3
  120. data/data/Antarctica/Macquarie +58 -3
  121. data/data/Antarctica/Syowa +1 -1
  122. data/data/Antarctica/Vostok +4 -1
  123. data/data/Arctic/Longyearbyen +23 -21
  124. data/data/Asia/Almaty +2 -1
  125. data/data/Asia/Amman +3 -35
  126. data/data/Asia/Brunei +18 -2
  127. data/data/Asia/Choibalsan +46 -47
  128. data/data/Asia/Chongqing +3 -1
  129. data/data/Asia/Chungking +3 -1
  130. data/data/Asia/Damascus +1 -33
  131. data/data/Asia/Dili +2 -2
  132. data/data/Asia/Gaza +46 -40
  133. data/data/Asia/Harbin +3 -1
  134. data/data/Asia/Hebron +46 -40
  135. data/data/Asia/Ho_Chi_Minh +4 -4
  136. data/data/Asia/Hong_Kong +20 -20
  137. data/data/Asia/Istanbul +22 -36
  138. data/data/Asia/Jerusalem +37 -31
  139. data/data/Asia/Kuala_Lumpur +3 -3
  140. data/data/Asia/Manila +14 -10
  141. data/data/Asia/Qostanay +53 -0
  142. data/data/Asia/Qyzylorda +2 -1
  143. data/data/Asia/Saigon +4 -4
  144. data/data/Asia/Seoul +9 -1
  145. data/data/Asia/Shanghai +3 -1
  146. data/data/Asia/Singapore +1 -1
  147. data/data/Asia/Tehran +8 -39
  148. data/data/Asia/Tel_Aviv +37 -31
  149. data/data/Atlantic/Azores +23 -28
  150. data/data/Atlantic/Bermuda +29 -2
  151. data/data/Atlantic/Jan_Mayen +23 -21
  152. data/data/Atlantic/Madeira +21 -28
  153. data/data/Atlantic/Reykjavik +1 -68
  154. data/data/Australia/ACT +9 -9
  155. data/data/Australia/Adelaide +9 -9
  156. data/data/Australia/Brisbane +9 -9
  157. data/data/Australia/Broken_Hill +9 -9
  158. data/data/Australia/Canberra +9 -9
  159. data/data/Australia/Currie +22 -10
  160. data/data/Australia/Darwin +8 -8
  161. data/data/Australia/Eucla +7 -7
  162. data/data/Australia/Hobart +12 -8
  163. data/data/Australia/Lindeman +9 -9
  164. data/data/Australia/Melbourne +9 -9
  165. data/data/Australia/NSW +9 -9
  166. data/data/Australia/North +8 -8
  167. data/data/Australia/Perth +7 -7
  168. data/data/Australia/Queensland +9 -9
  169. data/data/Australia/South +9 -9
  170. data/data/Australia/Sydney +9 -9
  171. data/data/Australia/Tasmania +12 -8
  172. data/data/Australia/Victoria +9 -9
  173. data/data/Australia/West +7 -7
  174. data/data/Australia/Yancowinna +9 -9
  175. data/data/Brazil/East +1 -40
  176. data/data/CET +56 -7
  177. data/data/CST6CDT +90 -3
  178. data/data/Canada/Eastern +2 -2
  179. data/data/Canada/Mountain +1 -5
  180. data/data/Canada/Pacific +2 -2
  181. data/data/Canada/Yukon +4 -40
  182. data/data/Chile/Continental +11 -11
  183. data/data/Chile/EasterIsland +2 -2
  184. data/data/EET +24 -8
  185. data/data/EST +3 -1
  186. data/data/EST5EDT +90 -3
  187. data/data/Egypt +32 -0
  188. data/data/Eire +2 -2
  189. data/data/Etc/UCT +1 -1
  190. data/data/Europe/Amsterdam +60 -55
  191. data/data/Europe/Brussels +2 -2
  192. data/data/Europe/Budapest +24 -24
  193. data/data/Europe/Copenhagen +23 -14
  194. data/data/Europe/Dublin +2 -2
  195. data/data/Europe/Istanbul +22 -36
  196. data/data/Europe/Kaliningrad +6 -5
  197. data/data/Europe/Kiev +8 -8
  198. data/data/Europe/Kirov +44 -44
  199. data/data/Europe/Kyiv +124 -0
  200. data/data/Europe/Lisbon +25 -22
  201. data/data/Europe/Luxembourg +38 -36
  202. data/data/Europe/Monaco +9 -10
  203. data/data/Europe/Oslo +23 -21
  204. data/data/Europe/Paris +3 -3
  205. data/data/Europe/Rome +2 -2
  206. data/data/Europe/San_Marino +2 -2
  207. data/data/Europe/Simferopol +10 -10
  208. data/data/Europe/Stockholm +28 -5
  209. data/data/Europe/Uzhgorod +18 -17
  210. data/data/Europe/Vatican +2 -2
  211. data/data/Europe/Vienna +2 -2
  212. data/data/Europe/Volgograd +48 -47
  213. data/data/Europe/Zaporozhye +17 -18
  214. data/data/HST +8 -1
  215. data/data/Hongkong +20 -20
  216. data/data/Iceland +1 -68
  217. data/data/Indian/Antananarivo +5 -4
  218. data/data/Indian/Christmas +2 -1
  219. data/data/Indian/Cocos +4 -1
  220. data/data/Indian/Comoro +5 -4
  221. data/data/Indian/Kerguelen +2 -1
  222. data/data/Indian/Mahe +1 -1
  223. data/data/Indian/Mayotte +5 -4
  224. data/data/Indian/Reunion +1 -1
  225. data/data/Iran +8 -39
  226. data/data/Israel +37 -31
  227. data/data/Kwajalein +5 -2
  228. data/data/MET +188 -139
  229. data/data/MST +12 -1
  230. data/data/MST7MDT +12 -3
  231. data/data/Mexico/BajaNorte +46 -8
  232. data/data/Mexico/BajaSur +5 -39
  233. data/data/Mexico/General +4 -36
  234. data/data/PRC +3 -1
  235. data/data/PST8PDT +39 -2
  236. data/data/Pacific/Apia +1 -36
  237. data/data/Pacific/Chuuk +2 -1
  238. data/data/Pacific/Easter +2 -2
  239. data/data/Pacific/Efate +5 -3
  240. data/data/Pacific/Enderbury +2 -2
  241. data/data/Pacific/Fiji +5 -40
  242. data/data/Pacific/Funafuti +1 -1
  243. data/data/Pacific/Guam +19 -1
  244. data/data/Pacific/Kanton +4 -0
  245. data/data/Pacific/Kosrae +8 -2
  246. data/data/Pacific/Kwajalein +5 -2
  247. data/data/Pacific/Majuro +1 -2
  248. data/data/Pacific/Nauru +3 -3
  249. data/data/Pacific/Niue +2 -3
  250. data/data/Pacific/Norfolk +42 -3
  251. data/data/Pacific/Palau +2 -1
  252. data/data/Pacific/Pohnpei +1 -1
  253. data/data/Pacific/Ponape +1 -1
  254. data/data/Pacific/Rarotonga +3 -2
  255. data/data/Pacific/Saipan +19 -1
  256. data/data/Pacific/Tongatapu +3 -3
  257. data/data/Pacific/Truk +2 -1
  258. data/data/Pacific/Wake +1 -1
  259. data/data/Pacific/Wallis +1 -1
  260. data/data/Pacific/Yap +2 -1
  261. data/data/Portugal +25 -22
  262. data/data/ROK +9 -1
  263. data/data/Singapore +1 -1
  264. data/data/Turkey +22 -36
  265. data/data/UCT +1 -1
  266. data/data/US/Michigan +5 -1
  267. data/data/WET +106 -4
  268. data/lib/timezone/error.rb +6 -0
  269. data/lib/timezone/loader.rb +8 -5
  270. data/lib/timezone/lookup/geonames.rb +1 -0
  271. data/lib/timezone/lookup/google.rb +3 -2
  272. data/lib/timezone/lookup.rb +3 -2
  273. data/lib/timezone/parser.rb +33 -18
  274. data/lib/timezone/version.rb +1 -1
  275. data/lib/timezone/zone.rb +17 -17
  276. data/test/test_timezone.rb +2 -4
  277. data/test/timezone/lookup/test_geonames.rb +16 -9
  278. data/test/timezone/lookup/test_google.rb +7 -2
  279. data/test/timezone/lookup/test_test.rb +1 -0
  280. data/test/timezone/test_lookup.rb +5 -5
  281. data/test/timezone/test_zone.rb +4 -4
  282. data/timezone.gemspec +10 -5
  283. metadata +63 -16
  284. data/.travis.yml +0 -12
  285. data/data/US/Pacific-New +0 -189
@@ -55,6 +55,7 @@ module Timezone
55
55
  return unless data['gmtOffset'].is_a? Numeric
56
56
 
57
57
  return 'Etc/UTC' if data['gmtOffset'].zero?
58
+
58
59
  "Etc/GMT#{format('%+d', -data['gmtOffset'])}"
59
60
  end
60
61
 
@@ -14,7 +14,7 @@ module Timezone
14
14
  class Google < ::Timezone::Lookup::Basic
15
15
  # Indicates that no time zone data could be found for the specified
16
16
  # <lat, lng>. This can occur if the query is incomplete or ambiguous.
17
- NO_TIMEZONE_INFORMATION = 'ZERO_RESULTS'.freeze
17
+ NO_TIMEZONE_INFORMATION = 'ZERO_RESULTS'
18
18
 
19
19
  def initialize(config)
20
20
  if config.api_key.nil?
@@ -34,7 +34,8 @@ module Timezone
34
34
  raise(Timezone::Error::Google, '403 Forbidden')
35
35
  end
36
36
 
37
- return unless response.code =~ /^2\d\d$/
37
+ return unless /^2\d\d$/.match?(response.code)
38
+
38
39
  data = JSON.parse(response.body)
39
40
 
40
41
  return if data['status'] == NO_TIMEZONE_INFORMATION
@@ -4,12 +4,13 @@ require 'timezone/lookup/geonames'
4
4
  require 'timezone/lookup/google'
5
5
  require 'timezone/lookup/test'
6
6
  require 'timezone/net_http_client'
7
+ require 'ostruct'
7
8
 
8
9
  module Timezone
9
10
  # Configure timezone lookups.
10
11
  module Lookup
11
12
  class << self
12
- MISSING_LOOKUP = 'No lookup configured'.freeze
13
+ MISSING_LOOKUP = 'No lookup configured'
13
14
  private_constant :MISSING_LOOKUP
14
15
 
15
16
  # Returns the lookup object
@@ -45,7 +46,7 @@ module Timezone
45
46
  test: ::Timezone::Lookup::Test
46
47
  }.freeze
47
48
 
48
- INVALID_LOOKUP = 'Invalid lookup specified'.freeze
49
+ INVALID_LOOKUP = 'Invalid lookup specified'
49
50
 
50
51
  attr_reader :config
51
52
 
@@ -9,30 +9,45 @@ module Timezone
9
9
  MIN_YEAR = -500
10
10
  MAX_YEAR = 2039
11
11
 
12
- LINE = /\s*(.+)\s*=\s*(.+)\s*isdst=(\d+)\s*gmtoff=([\+\-]*\d+)/
12
+ LINE = /\s*(.+)\s*=\s*(.+)\s*isdst=(\d+)\s*gmtoff=([+\-]*\d+)/.freeze
13
13
 
14
- ZONEINFO_DIR = '/usr/share/zoneinfo'.freeze
14
+ # Bookkeeping files that we do not want to parse.
15
+ IGNORE = ['leapseconds', 'posixrules', 'tzdata.zi'].freeze
15
16
 
16
- attr_reader :zoneinfo
17
-
18
- def initialize(zoneinfo = ZONEINFO_DIR)
19
- @zoneinfo = zoneinfo
17
+ def initialize(root)
18
+ @config = Config.new(root)
20
19
  end
21
20
 
22
21
  def perform
23
22
  FileUtils.rm_rf('data')
24
23
 
25
- Dir["#{zoneinfo}/posix/**/*"].each do |file|
24
+ Dir["#{@config.zoneinfo}/**/*"].each do |file|
26
25
  next if File.directory?(file)
26
+ next if file.end_with?('.tab')
27
+ next if IGNORE.include?(File.basename(file))
28
+
27
29
  parse(file)
28
30
  end
29
31
  end
30
32
 
33
+ # Represents a timezone database config.
34
+ class Config
35
+ def initialize(root)
36
+ @root = root
37
+ @zoneinfo = File.join(@root, 'usr/share/zoneinfo')
38
+ @zdump = File.join(@root, 'usr/bin/zdump')
39
+ end
40
+
41
+ attr_reader :root, :zoneinfo, :zdump
42
+ end
43
+
44
+ private_constant :Config
45
+
31
46
  # Represents a single timezone data file line for a reference timezone.
32
47
  class RefLine
33
- def initialize(zone)
48
+ def initialize(config, file)
34
49
  first =
35
- `zdump -i posix/#{zone}`
50
+ `#{config.zdump} -i #{file}`
36
51
  .split("\n")
37
52
  .reject(&:empty?)
38
53
  .reject { |line| line.start_with?('TZ=') }
@@ -51,7 +66,7 @@ module Timezone
51
66
  def parse_offset(offset)
52
67
  arity = offset.start_with?('-') ? -1 : 1
53
68
 
54
- match = offset.match(/^[\-\+](\d{2})$/)
69
+ match = offset.match(/^[\-+](\d{2})$/)
55
70
  arity * match[1].to_i * 60 * 60
56
71
  end
57
72
  end
@@ -62,10 +77,10 @@ module Timezone
62
77
  class Line
63
78
  attr_accessor :source, :name, :dst, :offset
64
79
 
65
- SOURCE_FORMAT = '%a %b %e %H:%M:%S %Y %Z'.freeze
80
+ SOURCE_FORMAT = '%a %b %e %H:%M:%S %Y %Z'
66
81
 
67
82
  def initialize(match)
68
- self.source = Time.strptime(match[1] + 'C', SOURCE_FORMAT).to_i
83
+ self.source = Time.strptime("#{match[1]}C", SOURCE_FORMAT).to_i
69
84
  self.name = match[2].split(' ').last
70
85
  self.dst = match[3].to_i
71
86
  self.offset = match[4].to_i
@@ -85,15 +100,15 @@ module Timezone
85
100
  private
86
101
 
87
102
  def parse(file)
88
- zone = file.gsub("#{zoneinfo}/posix/", '')
103
+ zone = file.gsub("#{@config.zoneinfo}/", '')
89
104
  print "Parsing #{zone}... "
90
- data = zdump(zone)
105
+ data = zdump(file)
91
106
 
92
107
  last = 0
93
108
  result = []
94
109
 
95
110
  data.split("\n").each do |line|
96
- match = line.gsub('posix/' + zone + ' ', '').match(LINE)
111
+ match = line.gsub(/^#{file}\s+/, '').match(LINE)
97
112
  next if match.nil?
98
113
 
99
114
  line = Line.new(match)
@@ -112,14 +127,14 @@ module Timezone
112
127
  result << line
113
128
  end
114
129
 
115
- result << RefLine.new(zone) if result.empty?
130
+ result << RefLine.new(@config, file) if result.empty?
116
131
 
117
132
  write(zone, result)
118
133
  puts 'DONE'
119
134
  end
120
135
 
121
- def zdump(zone)
122
- `zdump -v -c #{MIN_YEAR},#{MAX_YEAR} posix/#{zone}`
136
+ def zdump(file)
137
+ `#{@config.zdump} -V -c #{MIN_YEAR},#{MAX_YEAR} #{file}`
123
138
  end
124
139
 
125
140
  def write(zone, data)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Timezone
4
- VERSION = '1.3.2'.freeze
4
+ VERSION = '1.3.30'
5
5
  end
data/lib/timezone/zone.rb CHANGED
@@ -6,7 +6,6 @@ require 'time'
6
6
 
7
7
  require 'timezone/loader'
8
8
  require 'timezone/error'
9
- require 'timezone/loader'
10
9
 
11
10
  module Timezone
12
11
  # This object represents a real-world timezone. Each instance provides
@@ -179,10 +178,6 @@ module Timezone
179
178
 
180
179
  private
181
180
 
182
- def private_rules
183
- @rules ||= Loader.load(name)
184
- end
185
-
186
181
  def sanitize(time)
187
182
  time.to_time
188
183
  end
@@ -200,11 +195,15 @@ module Timezone
200
195
 
201
196
  def rule_for_local(local)
202
197
  local = local.to_i
198
+ rules = Loader.load(name)
203
199
 
204
200
  # For each rule, convert the local time into the UTC equivalent for
205
201
  # that rule offset, and then check if the UTC time matches the rule.
206
- index = binary_search(local) { |t, r| match?(t - r[OFFSET_BIT], r) }
207
- match = private_rules[index]
202
+ index =
203
+ binary_search(rules, local) do |t, r|
204
+ match?(t - r[OFFSET_BIT], r)
205
+ end
206
+ match = rules[index]
208
207
 
209
208
  utc = local - match[OFFSET_BIT]
210
209
 
@@ -213,7 +212,7 @@ module Timezone
213
212
  return RuleSet.new(:missing, [match]) if rule_for_utc(utc) != match
214
213
 
215
214
  # If the match is the last rule, then return it.
216
- return RuleSet.new(:single, [match]) if index == private_rules.length - 1
215
+ return RuleSet.new(:single, [match]) if index == rules.length - 1
217
216
 
218
217
  # If the UTC equivalent time falls within the last hour(s) of the time
219
218
  # change which were replayed during a fall-back in time, then return
@@ -234,10 +233,10 @@ module Timezone
234
233
  last_hour =
235
234
  match[SOURCE_BIT] -
236
235
  match[OFFSET_BIT] +
237
- private_rules[index + 1][OFFSET_BIT]
236
+ rules[index + 1][OFFSET_BIT]
238
237
 
239
238
  if utc > last_hour
240
- RuleSet.new(:double, private_rules[index..(index + 1)])
239
+ RuleSet.new(:double, rules[index..(index + 1)])
241
240
  else
242
241
  RuleSet.new(:single, [match])
243
242
  end
@@ -245,27 +244,28 @@ module Timezone
245
244
 
246
245
  def rule_for_utc(time)
247
246
  time = time.to_i
247
+ rules = Loader.load(name)
248
248
 
249
- private_rules[binary_search(time) { |t, r| match?(t, r) }]
249
+ rules[binary_search(rules, time) { |t, r| match?(t, r) }]
250
250
  end
251
251
 
252
252
  # Find the first rule that matches using binary search.
253
- def binary_search(time, from = 0, to = nil, &block)
254
- to = private_rules.length - 1 if to.nil?
253
+ def binary_search(rules, time, from = 0, to = nil, &block)
254
+ to = rules.length - 1 if to.nil?
255
255
 
256
256
  return from if from == to
257
257
 
258
258
  mid = (from + to).div(2)
259
259
 
260
- unless yield(time, private_rules[mid])
261
- return binary_search(time, mid + 1, to, &block)
260
+ unless yield(time, rules[mid])
261
+ return binary_search(rules, time, mid + 1, to, &block)
262
262
  end
263
263
 
264
264
  return mid if mid.zero?
265
265
 
266
- return mid unless yield(time, private_rules[mid - 1])
266
+ return mid unless yield(time, rules[mid - 1])
267
267
 
268
- binary_search(time, from, mid - 1, &block)
268
+ binary_search(rules, time, from, mid - 1, &block)
269
269
  end
270
270
  end
271
271
  end
@@ -32,13 +32,11 @@ class TestTimezone < ::Minitest::Test
32
32
  end
33
33
 
34
34
  def test_fetch_warning
35
- warning = false
36
-
37
- Timezone.stub(:warn, ->(_) { warning = true }) do
35
+ _out, err = capture_io do
38
36
  Timezone.fetch('foo/bar', 'a') { 'b' }
39
37
  end
40
38
 
41
- assert warning, 'warning was not issued'
39
+ assert_equal "warning: block supersedes default value argument\n", err
42
40
  end
43
41
 
44
42
  def test_lookup
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'timezone/lookup/geonames'
4
4
  require 'minitest/autorun'
5
+ require 'ostruct'
5
6
  require_relative '../../http_test_client'
6
7
 
7
8
  class TestGeonames < ::Minitest::Test
@@ -19,6 +20,10 @@ class TestGeonames < ::Minitest::Test
19
20
  }
20
21
  end
21
22
 
23
+ def lookup_file(file_name, &block)
24
+ lookup(File.open(File.join(mock_path, file_name)).read, &block)
25
+ end
26
+
22
27
  def lookup(body = nil, &_block)
23
28
  config = OpenStruct.new
24
29
  config.username = 'timezone'
@@ -40,23 +45,25 @@ class TestGeonames < ::Minitest::Test
40
45
  end
41
46
 
42
47
  def test_lookup
43
- mine = lookup(File.open(mock_path + '/lat_lon_coords.txt').read)
48
+ mine = lookup_file('/lat_lon_coords.txt')
44
49
 
45
50
  assert_equal 'Australia/Adelaide', mine.lookup(*coordinates)
46
51
  end
47
52
 
48
53
  def test_lookup_with_etc
49
54
  etc_data.each do |key, data|
50
- body = File.open(mock_path + "/lat_lon_coords_#{key}.txt").read
51
- mine = lookup(body) { |c| c.offset_etc_zones = true }
55
+ mine = lookup_file("/lat_lon_coords_#{key}.txt") do |c|
56
+ c.offset_etc_zones = true
57
+ end
52
58
 
53
59
  assert_equal data[:name], mine.lookup(*data[:coordinates])
54
60
  end
55
61
  end
56
62
 
57
63
  def test_wrong_offset
58
- body = File.open(mock_path + '/lat_lon_coords_wrong_offset.txt').read
59
- mine = lookup(body) { |c| c.offset_etc_zones = true }
64
+ mine = lookup_file('/lat_lon_coords_wrong_offset.txt') do |c|
65
+ c.offset_etc_zones = true
66
+ end
60
67
 
61
68
  assert_nil mine.lookup(*coordinates)
62
69
  end
@@ -80,7 +87,7 @@ class TestGeonames < ::Minitest::Test
80
87
  end
81
88
 
82
89
  def test_api_limit
83
- mine = lookup(File.open(mock_path + '/api_limit_reached.json').read)
90
+ mine = lookup_file('/api_limit_reached.json')
84
91
 
85
92
  assert_exception(
86
93
  mine,
@@ -90,19 +97,19 @@ class TestGeonames < ::Minitest::Test
90
97
  end
91
98
 
92
99
  def test_invalid_latlong
93
- mine = lookup(File.open(mock_path + '/invalid_latlong.json').read)
100
+ mine = lookup_file('/invalid_latlong.json')
94
101
 
95
102
  assert_exception(mine, 'invalid lat/lng')
96
103
  end
97
104
 
98
105
  def test_no_result_found
99
- mine = lookup(File.open(mock_path + '/no_result_found.json').read)
106
+ mine = lookup_file('/no_result_found.json')
100
107
 
101
108
  assert_nil(mine.lookup(10, 10))
102
109
  end
103
110
 
104
111
  def test_invalid_parameter
105
- mine = lookup(File.open(mock_path + '/invalid_parameter.json').read)
112
+ mine = lookup_file('/invalid_parameter.json')
106
113
 
107
114
  assert_exception(mine, 'error parsing parameter')
108
115
  end
@@ -3,6 +3,7 @@
3
3
  require 'timezone/lookup/google'
4
4
  require 'minitest/autorun'
5
5
  require 'timecop'
6
+ require 'ostruct'
6
7
  require_relative '../../http_test_client'
7
8
 
8
9
  class TestGoogle < ::Minitest::Test
@@ -12,6 +13,10 @@ class TestGoogle < ::Minitest::Test
12
13
  [-34.92771808058, 138.477041423321]
13
14
  end
14
15
 
16
+ def lookup_file(file_name, &block)
17
+ lookup(File.open(File.join(mock_path, file_name)).read, &block)
18
+ end
19
+
15
20
  def lookup(body = nil, &_block)
16
21
  config = OpenStruct.new
17
22
  config.api_key = 'MTIzYWJj'
@@ -33,7 +38,7 @@ class TestGoogle < ::Minitest::Test
33
38
  end
34
39
 
35
40
  def test_google_using_lat_long_coordinates
36
- mine = lookup(File.open(mock_path + '/google_lat_lon_coords.txt').read)
41
+ mine = lookup_file('/google_lat_lon_coords.txt')
37
42
 
38
43
  assert_equal 'Australia/Adelaide', mine.lookup(*coordinates)
39
44
  end
@@ -76,7 +81,7 @@ class TestGoogle < ::Minitest::Test
76
81
  end
77
82
 
78
83
  def test_no_result_found
79
- mine = lookup(File.open(mock_path + '/google_no_result_found.json').read)
84
+ mine = lookup_file('/google_no_result_found.json')
80
85
 
81
86
  assert_nil(mine.lookup(26.188703, -78.987053))
82
87
  end
@@ -3,6 +3,7 @@
3
3
  require 'timezone/lookup/test'
4
4
  require 'timezone'
5
5
  require 'minitest/autorun'
6
+ require 'ostruct'
6
7
 
7
8
  class TestTest < ::Minitest::Test
8
9
  parallelize_me!
@@ -8,7 +8,7 @@ class TestLookup < ::Minitest::Test
8
8
  Timezone::Lookup.config(:test)
9
9
 
10
10
  assert_equal Timezone::Lookup::Test,
11
- Timezone::Lookup.lookup.class
11
+ Timezone::Lookup.lookup.class
12
12
  end
13
13
 
14
14
  def test_geonames_config
@@ -17,10 +17,10 @@ class TestLookup < ::Minitest::Test
17
17
  end
18
18
 
19
19
  assert_equal Timezone::Lookup::Geonames,
20
- Timezone::Lookup.lookup.class
20
+ Timezone::Lookup.lookup.class
21
21
 
22
22
  assert_equal Timezone::NetHTTPClient,
23
- Timezone::Lookup.lookup.config.request_handler
23
+ Timezone::Lookup.lookup.config.request_handler
24
24
  end
25
25
 
26
26
  def test_google_config
@@ -29,10 +29,10 @@ class TestLookup < ::Minitest::Test
29
29
  end
30
30
 
31
31
  assert_equal Timezone::Lookup::Google,
32
- Timezone::Lookup.lookup.class
32
+ Timezone::Lookup.lookup.class
33
33
 
34
34
  assert_equal Timezone::NetHTTPClient,
35
- Timezone::Lookup.lookup.config.request_handler
35
+ Timezone::Lookup.lookup.config.request_handler
36
36
  end
37
37
 
38
38
  def test_custom_config
@@ -130,12 +130,12 @@ class TestZone < ::Minitest::Test
130
130
 
131
131
  # http://www.timeanddate.com/worldclock/clockchange.html?n=2364&year=1940
132
132
  def test_historical_time_change_in_hebron
133
- local = Time.strptime('1940-05-31T23:59:59 UTC', '%Y-%m-%dT%H:%M:%S %Z')
134
- utc = Time.strptime('1940-05-31T21:59:59 UTC', '%Y-%m-%dT%H:%M:%S %Z')
133
+ local = Time.strptime('1940-06-01T01:59:59 UTC', '%Y-%m-%dT%H:%M:%S %Z')
134
+ utc = Time.strptime('1940-05-31T23:59:59 UTC', '%Y-%m-%dT%H:%M:%S %Z')
135
135
  assert_equal local.to_i, zone('Asia/Hebron').time(utc).to_i
136
136
 
137
- local = Time.strptime('1940-06-01T01:00:00 UTC', '%Y-%m-%dT%H:%M:%S %Z')
138
- utc = Time.strptime('1940-05-31T22:00:00 UTC', '%Y-%m-%dT%H:%M:%S %Z')
137
+ local = Time.strptime('1940-06-01T03:00:00 UTC', '%Y-%m-%dT%H:%M:%S %Z')
138
+ utc = Time.strptime('1940-06-01T00:00:00 UTC', '%Y-%m-%dT%H:%M:%S %Z')
139
139
  assert_equal local.to_i, zone('Asia/Hebron').time(utc).to_i
140
140
  end
141
141
 
data/timezone.gemspec CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
- # -*- encoding: utf-8 -*-
3
2
 
4
- $:.push File.expand_path('../lib', __FILE__)
3
+ $:.push File.expand_path('lib', __dir__)
5
4
  require 'timezone/version'
6
5
 
7
6
  Gem::Specification.new do |s|
@@ -16,7 +15,9 @@ Gem::Specification.new do |s|
16
15
  s.description = 'Accurate current and historical timezones for Ruby with ' \
17
16
  'support for Geonames and Google latitude - longitude lookups.'
18
17
 
19
- s.rubyforge_project = 'timezone'
18
+ s.metadata = {
19
+ 'changelog_uri' => 'https://github.com/panthomakos/timezone/blob/master/CHANGES.markdown'
20
+ }
20
21
 
21
22
  s.files = `git ls-files`.split("\n")
22
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -27,8 +28,12 @@ Gem::Specification.new do |s|
27
28
  s.rdoc_options = ['--charset=UTF-8']
28
29
  s.require_paths = ['lib']
29
30
 
31
+ s.add_runtime_dependency('base64', '~> 0.2')
32
+ s.add_runtime_dependency('ostruct', '~> 0.6')
33
+
30
34
  s.add_development_dependency('minitest', '~> 5.8')
31
- s.add_development_dependency('rake', '~> 12')
32
- s.add_development_dependency('rubocop', '= 0.51')
35
+ s.add_development_dependency('rake', '~> 13')
36
+ s.add_development_dependency('rubocop', '= 1.5.1')
37
+ s.add_development_dependency('rubocop-performance', '= 1.5.1')
33
38
  s.add_development_dependency('timecop', '~> 0.8')
34
39
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timezone
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.3.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pan Thomakos
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-02 00:00:00.000000000 Z
11
+ date: 2025-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: base64
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ostruct
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: minitest
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -30,28 +58,42 @@ dependencies:
30
58
  requirements:
31
59
  - - "~>"
32
60
  - !ruby/object:Gem::Version
33
- version: '12'
61
+ version: '13'
34
62
  type: :development
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
- version: '12'
68
+ version: '13'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rubocop
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
73
  - - '='
46
74
  - !ruby/object:Gem::Version
47
- version: '0.51'
75
+ version: 1.5.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.5.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-performance
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 1.5.1
48
90
  type: :development
49
91
  prerelease: false
50
92
  version_requirements: !ruby/object:Gem::Requirement
51
93
  requirements:
52
94
  - - '='
53
95
  - !ruby/object:Gem::Version
54
- version: '0.51'
96
+ version: 1.5.1
55
97
  - !ruby/object:Gem::Dependency
56
98
  name: timecop
57
99
  requirement: !ruby/object:Gem::Requirement
@@ -76,10 +118,11 @@ extra_rdoc_files:
76
118
  - README.markdown
77
119
  - License.txt
78
120
  files:
121
+ - ".codeclimate.yml"
79
122
  - ".editorconfig"
123
+ - ".github/workflows/ci.yml"
80
124
  - ".gitignore"
81
125
  - ".rubocop.yml"
82
- - ".travis.yml"
83
126
  - CHANGES.markdown
84
127
  - CODE_OF_CONDUCT.md
85
128
  - CONTRIBUTING.markdown
@@ -183,9 +226,11 @@ files:
183
226
  - data/America/Cayman
184
227
  - data/America/Chicago
185
228
  - data/America/Chihuahua
229
+ - data/America/Ciudad_Juarez
186
230
  - data/America/Coral_Harbour
187
231
  - data/America/Cordoba
188
232
  - data/America/Costa_Rica
233
+ - data/America/Coyhaique
189
234
  - data/America/Creston
190
235
  - data/America/Cuiaba
191
236
  - data/America/Curacao
@@ -263,6 +308,7 @@ files:
263
308
  - data/America/North_Dakota/Beulah
264
309
  - data/America/North_Dakota/Center
265
310
  - data/America/North_Dakota/New_Salem
311
+ - data/America/Nuuk
266
312
  - data/America/Ojinaga
267
313
  - data/America/Panama
268
314
  - data/America/Pangnirtung
@@ -389,6 +435,7 @@ files:
389
435
  - data/Asia/Pontianak
390
436
  - data/Asia/Pyongyang
391
437
  - data/Asia/Qatar
438
+ - data/Asia/Qostanay
392
439
  - data/Asia/Qyzylorda
393
440
  - data/Asia/Rangoon
394
441
  - data/Asia/Riyadh
@@ -535,6 +582,7 @@ files:
535
582
  - data/Europe/Kaliningrad
536
583
  - data/Europe/Kiev
537
584
  - data/Europe/Kirov
585
+ - data/Europe/Kyiv
538
586
  - data/Europe/Lisbon
539
587
  - data/Europe/Ljubljana
540
588
  - data/Europe/London
@@ -630,6 +678,7 @@ files:
630
678
  - data/Pacific/Guam
631
679
  - data/Pacific/Honolulu
632
680
  - data/Pacific/Johnston
681
+ - data/Pacific/Kanton
633
682
  - data/Pacific/Kiritimati
634
683
  - data/Pacific/Kosrae
635
684
  - data/Pacific/Kwajalein
@@ -674,7 +723,6 @@ files:
674
723
  - data/US/Michigan
675
724
  - data/US/Mountain
676
725
  - data/US/Pacific
677
- - data/US/Pacific-New
678
726
  - data/US/Samoa
679
727
  - data/UTC
680
728
  - data/Universal
@@ -726,8 +774,9 @@ files:
726
774
  homepage: https://github.com/panthomakos/timezone
727
775
  licenses:
728
776
  - MIT
729
- metadata: {}
730
- post_install_message:
777
+ metadata:
778
+ changelog_uri: https://github.com/panthomakos/timezone/blob/master/CHANGES.markdown
779
+ post_install_message:
731
780
  rdoc_options:
732
781
  - "--charset=UTF-8"
733
782
  require_paths:
@@ -743,11 +792,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
743
792
  - !ruby/object:Gem::Version
744
793
  version: '0'
745
794
  requirements: []
746
- rubyforge_project: timezone
747
- rubygems_version: 2.6.11
748
- signing_key:
795
+ rubygems_version: 3.4.19
796
+ signing_key:
749
797
  specification_version: 4
750
- summary: timezone-1.3.2
798
+ summary: timezone-1.3.30
751
799
  test_files:
752
800
  - test/data/Helsinki_rules_without_timestamps.json
753
801
  - test/data/asia
@@ -776,4 +824,3 @@ test_files:
776
824
  - test/timezone/test_mathn_compatibility.rb
777
825
  - test/timezone/test_nil_zone.rb
778
826
  - test/timezone/test_zone.rb
779
- has_rdoc: