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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b310de1d20cfb9b20cba87249ee230e5baff3efbab063fd7c87b21e7c5e458af
4
- data.tar.gz: 7434225f05490776ced760c84f522b41b7ff2afc903a2cb4c1729c7b5a71d748
3
+ metadata.gz: ab5db4fd6e68687e6761f890c37122d5ba3c393f267c2efdf7320f66cdf81b9e
4
+ data.tar.gz: 153766d2364660656ca42179ce52d649a179c600ea21ea1713d97381af10c874
5
5
  SHA512:
6
- metadata.gz: ded78e81fcfcad3917c824512de4c0e8eb902ef37f45fc7300610796100e4d367a338fabe1e4aa18b8237012208268bb3c55efc016021099b055ffddcd3ab34c
7
- data.tar.gz: 81050bfeefe7dc5aa8ad492cece4975c8382178037a445f97957005e11f9242f1d6291073650031687fa90fa79df87403587368946b23c33787200789a33a8fe
6
+ metadata.gz: 5680d6235c68c8d70d8c89b45d23844db662b3dad0a8090bbf9abed9c23be48f835ae6bbb260a55eac74af3bb11ea61a9ae3ab53adb88e7831b0b4292dddf5d5
7
+ data.tar.gz: 3a04b0ee0c20e672059eef0122279b5cc8f082baab15b910cc547b39cb4af349065804605d83ee3e90c66d1b2e4ddef5077cb63f446ffad9f4ad187d26dad1a0
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ziptz
2
2
  [![Version](http://img.shields.io/gem/v/ziptz.svg?style=flat)](https://rubygems.org/gems/ziptz)
3
- [![Build Status](https://github.com/infused/ziptz/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/infused/ziptz/actions/workflows/build.yml)
3
+ [![Build Status](https://github.com/infused/ziptz/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/infused/ziptz/actions/workflows/build.yml)
4
4
  [![Total Downloads](https://img.shields.io/gem/dt/ziptz.svg)](https://rubygems.org/gems/ziptz/)
5
5
  [![License](https://img.shields.io/github/license/infused/ziptz.svg)](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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Ziptz
2
- VERSION = '5.1.2'.freeze
4
+ VERSION = '6.1.0'
3
5
  end
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
- def self.instance
6
- @instance ||= new
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
- @db ||= begin
11
- db = SQLite3::Database.open(tz_data_path)
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)&.dig('time_zone')
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)&.dig('offset')
28
+ time_zone_info(zip).dig('offset')
23
29
  end
24
30
 
25
31
  def time_zone_uses_dst?(zip)
26
- tz_info = time_zone_info(zip)
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 = <<-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
- return unless zip
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
- end
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
- def tz_data_path
55
- File.join(File.dirname(__FILE__), '..', 'data', 'tz.db')
57
+ result
56
58
  end
57
59
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ziptz'
2
4
  require 'yaml'
3
5
  require 'rspec'
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(:ziptz) { described_class.new }
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 'returns nil' do
27
- expect(ziptz.time_zone_name('xyz')).to be_nil
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 'returns nil' do
33
- expect(ziptz.time_zone_name(nil)).to be_nil
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 eq true
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 eq false
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 eq true
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 eq false
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 'returns nil' do
65
- expect(ziptz.time_zone_uses_dst?('xyz')).to be_nil
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 'returns nil' do
85
- expect(ziptz.time_zone_offset('xyz')).to be_nil
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 '#instance' do
107
- context 'when given a 5 digit zip code' do
108
- it 'matches the behavior of Ziptz.new' do
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
- context 'when called twice' do
114
- it 'returns identical instances' do
115
- expect(described_class.instance.object_id).to eq described_class.instance.object_id
116
- end
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.1.0'
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: 5.1.2
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: 2024-11-24 00:00:00.000000000 Z
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.1.0
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: 3.5.9
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