ziptz 5.1.2 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -2
- data/lib/version.rb +3 -1
- data/lib/ziptz.rb +18 -16
- data/spec/spec_helper.rb +2 -0
- data/spec/ziptz_spec.rb +36 -22
- data/ziptz.gemspec +3 -1
- metadata +6 -9
- /data/{data → spec/fixtures}/tz.db +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ab5db4fd6e68687e6761f890c37122d5ba3c393f267c2efdf7320f66cdf81b9e
|
|
4
|
+
data.tar.gz: 153766d2364660656ca42179ce52d649a179c600ea21ea1713d97381af10c874
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5680d6235c68c8d70d8c89b45d23844db662b3dad0a8090bbf9abed9c23be48f835ae6bbb260a55eac74af3bb11ea61a9ae3ab53adb88e7831b0b4292dddf5d5
|
|
7
|
+
data.tar.gz: 3a04b0ee0c20e672059eef0122279b5cc8f082baab15b910cc547b39cb4af349065804605d83ee3e90c66d1b2e4ddef5077cb63f446ffad9f4ad187d26dad1a0
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ziptz
|
|
2
2
|
[](https://rubygems.org/gems/ziptz)
|
|
3
|
-
[](https://github.com/infused/ziptz/actions/workflows/build.yml)
|
|
4
4
|
[](https://rubygems.org/gems/ziptz/)
|
|
5
5
|
[](https://github.com/infused/ziptz)
|
|
6
6
|
|
|
@@ -20,11 +20,21 @@ Add the gem to your Gemfile:
|
|
|
20
20
|
|
|
21
21
|
gem 'ziptz'
|
|
22
22
|
|
|
23
|
+
## Data File Requirement
|
|
24
|
+
|
|
25
|
+
Starting with version 6.0.0, you'll need to supply your own time zone SQLite database file. You can subscribe to the required dataset here:
|
|
26
|
+
[ZIP Code Time Zones Dataset](https://www.infused-data.com/zip-code-time-zones/)
|
|
27
|
+
|
|
23
28
|
## Usage
|
|
24
29
|
|
|
30
|
+
First, initialize Ziptz with the path to your time zone database file:
|
|
31
|
+
|
|
32
|
+
z = Ziptz.new('/path/to/your/tz.db')
|
|
33
|
+
# or using keyword argument
|
|
34
|
+
z = Ziptz.new(db: '/path/to/your/tz.db')
|
|
35
|
+
|
|
25
36
|
Get the time zone name for any ZIP code:
|
|
26
37
|
|
|
27
|
-
z = Ziptz.new
|
|
28
38
|
z.time_zone_name('97213') #=> "America/Los_Angeles"
|
|
29
39
|
|
|
30
40
|
Get the time zone offset for any ZIP code:
|
data/lib/version.rb
CHANGED
data/lib/ziptz.rb
CHANGED
|
@@ -1,36 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'sqlite3'
|
|
2
4
|
require 'version'
|
|
3
5
|
|
|
4
6
|
class Ziptz
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
class ZipNotFound < StandardError; end
|
|
8
|
+
|
|
9
|
+
def initialize(*args, db: nil)
|
|
10
|
+
@db_path = args[0] || db
|
|
11
|
+
raise ArgumentError, 'Database path is required' if @db_path.nil? || @db_path.empty?
|
|
12
|
+
raise ArgumentError, 'Database file does not exist' unless File.exist?(@db_path)
|
|
7
13
|
end
|
|
8
14
|
|
|
9
15
|
def db
|
|
10
|
-
|
|
11
|
-
db = SQLite3::Database.open(
|
|
16
|
+
Thread.current[:ziptz_db] ||= begin
|
|
17
|
+
db = SQLite3::Database.open(@db_path)
|
|
12
18
|
db.results_as_hash = true
|
|
13
19
|
db
|
|
14
20
|
end
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
def time_zone_name(zip)
|
|
18
|
-
time_zone_info(zip)
|
|
24
|
+
time_zone_info(zip).dig('time_zone')
|
|
19
25
|
end
|
|
20
26
|
|
|
21
27
|
def time_zone_offset(zip)
|
|
22
|
-
time_zone_info(zip)
|
|
28
|
+
time_zone_info(zip).dig('offset')
|
|
23
29
|
end
|
|
24
30
|
|
|
25
31
|
def time_zone_uses_dst?(zip)
|
|
26
|
-
|
|
27
|
-
return unless tz_info
|
|
28
|
-
|
|
29
|
-
tz_info['observes_dst'] == 1
|
|
32
|
+
time_zone_info(zip)['observes_dst'] == 1
|
|
30
33
|
end
|
|
31
34
|
|
|
32
35
|
def zips(tz_name)
|
|
33
|
-
sql =
|
|
36
|
+
sql = <<~SQL
|
|
34
37
|
select zip_code
|
|
35
38
|
from zip_codes
|
|
36
39
|
where time_zone = ?
|
|
@@ -46,12 +49,11 @@ class Ziptz
|
|
|
46
49
|
protected
|
|
47
50
|
|
|
48
51
|
def time_zone_info(zip)
|
|
49
|
-
|
|
52
|
+
raise ZipNotFound, "Zip code not found: #{zip.inspect}" if zip.nil?
|
|
50
53
|
|
|
51
|
-
db.get_first_row('select * from zip_codes where zip_code = ? limit 1', zip[0, 5])
|
|
52
|
-
|
|
54
|
+
result = db.get_first_row('select * from zip_codes where zip_code = ? limit 1', zip[0, 5])
|
|
55
|
+
raise ZipNotFound, "Zip code not found: #{zip}" unless result
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
File.join(File.dirname(__FILE__), '..', 'data', 'tz.db')
|
|
57
|
+
result
|
|
56
58
|
end
|
|
57
59
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/ziptz_spec.rb
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
RSpec.describe Ziptz do
|
|
4
|
-
let(:
|
|
6
|
+
let(:db_path) { File.join(File.dirname(__FILE__), 'fixtures', 'tz.db') }
|
|
7
|
+
let(:ziptz) { described_class.new(db_path) }
|
|
5
8
|
|
|
6
9
|
describe 'when inspected' do
|
|
7
10
|
it 'does not show internal instance variables' do
|
|
@@ -23,14 +26,14 @@ RSpec.describe Ziptz do
|
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
context 'when there is no matching zipcode' do
|
|
26
|
-
it '
|
|
27
|
-
expect
|
|
29
|
+
it 'raises ZipNotFound' do
|
|
30
|
+
expect { ziptz.time_zone_name('xyz') }.to raise_error(Ziptz::ZipNotFound)
|
|
28
31
|
end
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
context 'when nil is passed' do
|
|
32
|
-
it '
|
|
33
|
-
expect
|
|
35
|
+
it 'raises ZipNotFound' do
|
|
36
|
+
expect { ziptz.time_zone_name(nil) }.to raise_error(Ziptz::ZipNotFound)
|
|
34
37
|
end
|
|
35
38
|
end
|
|
36
39
|
end
|
|
@@ -38,31 +41,31 @@ RSpec.describe Ziptz do
|
|
|
38
41
|
describe '#time_zone_uses_dst?' do
|
|
39
42
|
context 'when given a valid 5-digit zipcode' do
|
|
40
43
|
it 'returns true' do
|
|
41
|
-
expect(ziptz.time_zone_uses_dst?('97034')).to
|
|
44
|
+
expect(ziptz.time_zone_uses_dst?('97034')).to be true
|
|
42
45
|
end
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
context 'when given an invalid 5-digit zipcode' do
|
|
46
49
|
it 'returns false' do
|
|
47
|
-
expect(ziptz.time_zone_uses_dst?('85004')).to
|
|
50
|
+
expect(ziptz.time_zone_uses_dst?('85004')).to be false
|
|
48
51
|
end
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
context 'when given a valid 9-digit zipcode' do
|
|
52
55
|
it 'returns a true' do
|
|
53
|
-
expect(ziptz.time_zone_uses_dst?('97034-1234')).to
|
|
56
|
+
expect(ziptz.time_zone_uses_dst?('97034-1234')).to be true
|
|
54
57
|
end
|
|
55
58
|
end
|
|
56
59
|
|
|
57
60
|
context 'when given an invalid 9-digit zipcode' do
|
|
58
61
|
it 'returns false' do
|
|
59
|
-
expect(ziptz.time_zone_uses_dst?('85004-1234')).to
|
|
62
|
+
expect(ziptz.time_zone_uses_dst?('85004-1234')).to be false
|
|
60
63
|
end
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
context 'when there is no matching zipcode' do
|
|
64
|
-
it '
|
|
65
|
-
expect
|
|
67
|
+
it 'raises ZipNotFound' do
|
|
68
|
+
expect { ziptz.time_zone_uses_dst?('xyz') }.to raise_error(Ziptz::ZipNotFound)
|
|
66
69
|
end
|
|
67
70
|
end
|
|
68
71
|
end
|
|
@@ -81,8 +84,8 @@ RSpec.describe Ziptz do
|
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
context 'when there is no matching zipcode' do
|
|
84
|
-
it '
|
|
85
|
-
expect
|
|
87
|
+
it 'raises ZipNotFound' do
|
|
88
|
+
expect { ziptz.time_zone_offset('xyz') }.to raise_error(Ziptz::ZipNotFound)
|
|
86
89
|
end
|
|
87
90
|
end
|
|
88
91
|
end
|
|
@@ -103,17 +106,28 @@ RSpec.describe Ziptz do
|
|
|
103
106
|
end
|
|
104
107
|
end
|
|
105
108
|
|
|
106
|
-
describe '
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
expect(described_class.instance.time_zone_name('97034')).to eq ziptz.time_zone_name('97034')
|
|
110
|
-
end
|
|
109
|
+
describe 'initialization' do
|
|
110
|
+
it 'accepts database path as first argument' do
|
|
111
|
+
expect { described_class.new(db_path) }.to_not raise_error
|
|
111
112
|
end
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
it 'accepts database path as keyword argument' do
|
|
115
|
+
expect { described_class.new(db: db_path) }.to_not raise_error
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'raises an error when database path is nil' do
|
|
119
|
+
expect { described_class.new }.to raise_error(ArgumentError, 'Database path is required')
|
|
120
|
+
expect { described_class.new(db: nil) }.to raise_error(ArgumentError, 'Database path is required')
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'raises an error when database path is empty' do
|
|
124
|
+
expect { described_class.new('') }.to raise_error(ArgumentError, 'Database path is required')
|
|
125
|
+
expect { described_class.new(db: '') }.to raise_error(ArgumentError, 'Database path is required')
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'raises an error when database file does not exist' do
|
|
129
|
+
expect { described_class.new('nonexistent.db') }.to raise_error(ArgumentError, 'Database file does not exist')
|
|
130
|
+
expect { described_class.new(db: 'nonexistent.db') }.to raise_error(ArgumentError, 'Database file does not exist')
|
|
117
131
|
end
|
|
118
132
|
end
|
|
119
133
|
end
|
data/ziptz.gemspec
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
lib = File.expand_path('lib', __dir__)
|
|
2
4
|
$LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
|
3
5
|
require 'version'
|
|
@@ -17,7 +19,7 @@ Gem::Specification.new do |s|
|
|
|
17
19
|
s.extra_rdoc_files = ['README.md', 'LICENSE']
|
|
18
20
|
s.files = Dir['README.md', 'LICENSE', '{data,lib,spec}/**/*', 'ziptz.gemspec']
|
|
19
21
|
s.require_paths = ['lib']
|
|
20
|
-
s.required_ruby_version = '>= 3.
|
|
22
|
+
s.required_ruby_version = '>= 3.3.0'
|
|
21
23
|
s.metadata['rubygems_mfa_required'] = 'true'
|
|
22
24
|
s.add_dependency 'sqlite3', '~> 2.0'
|
|
23
25
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ziptz
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Keith Morrison
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: sqlite3
|
|
@@ -29,14 +28,14 @@ email: keithm@infused.org
|
|
|
29
28
|
executables: []
|
|
30
29
|
extensions: []
|
|
31
30
|
extra_rdoc_files:
|
|
32
|
-
- README.md
|
|
33
31
|
- LICENSE
|
|
32
|
+
- README.md
|
|
34
33
|
files:
|
|
35
34
|
- LICENSE
|
|
36
35
|
- README.md
|
|
37
|
-
- data/tz.db
|
|
38
36
|
- lib/version.rb
|
|
39
37
|
- lib/ziptz.rb
|
|
38
|
+
- spec/fixtures/tz.db
|
|
40
39
|
- spec/spec_helper.rb
|
|
41
40
|
- spec/ziptz_spec.rb
|
|
42
41
|
- ziptz.gemspec
|
|
@@ -45,7 +44,6 @@ licenses:
|
|
|
45
44
|
- MIT
|
|
46
45
|
metadata:
|
|
47
46
|
rubygems_mfa_required: 'true'
|
|
48
|
-
post_install_message:
|
|
49
47
|
rdoc_options:
|
|
50
48
|
- "--charset=UTF-8"
|
|
51
49
|
require_paths:
|
|
@@ -54,15 +52,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
54
52
|
requirements:
|
|
55
53
|
- - ">="
|
|
56
54
|
- !ruby/object:Gem::Version
|
|
57
|
-
version: 3.
|
|
55
|
+
version: 3.3.0
|
|
58
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
57
|
requirements:
|
|
60
58
|
- - ">="
|
|
61
59
|
- !ruby/object:Gem::Version
|
|
62
60
|
version: '0'
|
|
63
61
|
requirements: []
|
|
64
|
-
rubygems_version:
|
|
65
|
-
signing_key:
|
|
62
|
+
rubygems_version: 4.0.6
|
|
66
63
|
specification_version: 4
|
|
67
64
|
summary: TimeZone info for any 5-digit US zip code
|
|
68
65
|
test_files: []
|
|
File without changes
|