timezone 0.3.1 → 0.3.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 46a05b3cbaa15e1f491d73af323de8afaa25d1fd
4
+ data.tar.gz: f8f66464396431dbf25a5e4f2573829a1ac7fe58
5
+ SHA512:
6
+ metadata.gz: 68fd48be56823ac5a85b6f9c03c7d9a82356e056b6d3d503e5bb6f8b39a3f43d4692e1996929aab3f0eaef409963f49c25d07e9c86229a60d29dc02119564a4a
7
+ data.tar.gz: 60264e09a76c2a21c10d6cd2cf2c66551c48715dfac8a56b5b4d9568f94a1479adb2e60c185c1ed261133147a8ed343e0cd1108f475a20dd3cb3b9eba37e02fb
data/.gitignore CHANGED
@@ -5,3 +5,4 @@
5
5
  .idea/*
6
6
  Gemfile.lock
7
7
  pkg/*
8
+ .yardoc/
@@ -101,6 +101,27 @@ Finally, by default the **Zone#list** method will order the results by the timez
101
101
  c.order_list_by = :title
102
102
  end
103
103
 
104
+ ## Using Your Own HTTP Client
105
+
106
+ If you have non-standard http request needs or want to have more control over
107
+ API calls to Geonames, you can write your own very simple http client wrapper
108
+ instead of using the built-in default.
109
+
110
+ class MyHTTPClient
111
+ def initialize(protocol, host)
112
+ end
113
+
114
+ # Return a response object that responds to #body and #code
115
+ def get(url)
116
+ end
117
+ end
118
+
119
+ Timezone::Configure.begin do |c|
120
+ c.http_client = MyHTTPClient
121
+ end
122
+
123
+ For an example, see `Timezone::NetHTTPClient` which uses the standard `Net::HTTP` library to perform API calls.
124
+
104
125
  ## Build Status [![Build Status](https://secure.travis-ci.org/panthomakos/timezone.png?branch=master)](http://travis-ci.org/panthomakos/timezone)
105
126
 
106
127
  ## Code Quality [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/panthomakos/timezone)
@@ -1,22 +1,72 @@
1
+ require 'timezone/net_http_client'
2
+
1
3
  module Timezone
2
4
  # Configuration class for the Timezone gem.
3
5
  #
4
- # Timezone::Configure.begin do |c| ... end
6
+ # You'll want to sign up for a geonames username at
7
+ # {http://www.geonames.org/login Geonames}. Use the username to
8
+ # configure your application for latitude and longitude based
9
+ # timezone searches.
10
+ #
11
+ # If you aren't going to initialize timezone objects based on lat,lng
12
+ # then this configuration is not necessary.
5
13
  #
6
- # c.username = username - the geonames username you use to access the geonames timezone API.
14
+ # @example
15
+ # Timezone::Configure.begin do |c|
16
+ # c.url = 'api.geonames.org'
17
+ # c.username = 'foo-bar'
18
+ # end
7
19
  #
8
- # Signup for a geonames username at http://www.geonames.org/login. Use that username to configure
9
- # your application for latitude and longitude based timezone searches. If you aren't going to
10
- # initialize timezone objects based on latitude and longitude then this configuration is not necessary.
11
20
  class Configure
21
+ # The Geonames API URL
22
+ #
23
+ # @return [Sting]
24
+ # the Geonames API URL ('api.geonames.org')
12
25
  def self.url
13
26
  @@url ||= 'api.geonames.org'
14
27
  end
15
28
 
16
- def self.url= url
29
+ # The Geonames API URL
30
+ #
31
+ # @param [Sting] url
32
+ # the Geonames API URL
33
+ def self.url=(url)
17
34
  @@url = url
18
35
  end
19
36
 
37
+ # The Geonames API HTTP protocol
38
+ #
39
+ # @param [String] protocol
40
+ # the Geonames API HTTP procotol
41
+ def self.protocol=(protocol)
42
+ @@protocol = protocol
43
+ end
44
+
45
+ # The Geonames API HTTP protocol
46
+ #
47
+ # @return [Sting]
48
+ # the Geonames API URL ('api.geonames.org')
49
+ def self.protocol
50
+ @protocol ||= 'http'
51
+ end
52
+
53
+ # The HTTP client that handles requests to geonames
54
+ #
55
+ # @return [Object]
56
+ # the HTTP client ({Timezone::NetHTTPClient Timezone::NetHTTPClient})
57
+ def self.http_client
58
+ @@http_client ||= Timezone::NetHTTPClient
59
+ end
60
+
61
+ # The HTTP client that handles requests to geonames
62
+ #
63
+ # @param [Object] client
64
+ # the HTTP client that handles requests to geonames
65
+ #
66
+ def self.http_client=(client)
67
+ @@http_client = client
68
+ end
69
+
20
70
  def self.username
21
71
  @@username
22
72
  end
@@ -53,6 +103,5 @@ module Timezone
53
103
  def self.order_list_by=(order)
54
104
  @@order_by = order
55
105
  end
56
-
57
106
  end
58
107
  end
@@ -0,0 +1,23 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+
4
+ module Timezone
5
+ # A basic HTTP Client that handles requests to Geonames. You can create
6
+ # your own version of this class if you want to use a proxy or a
7
+ # different http library such as faraday.
8
+ #
9
+ # @example
10
+ # Timezone::Configure.begin do |c|
11
+ # c.http_client = Timezone::NetHTTPClient
12
+ # end
13
+ class NetHTTPClient
14
+ def initialize(protocol, host)
15
+ uri = URI.parse("#{protocol}://#{host}")
16
+ @http = Net::HTTP.new(uri.host, uri.port)
17
+ end
18
+
19
+ def get(url)
20
+ @http.request(Net::HTTP::Get.new(url))
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Timezone
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require 'json'
2
2
  require 'date'
3
3
  require 'time'
4
- require 'net/http'
4
+
5
5
  require File.expand_path(File.dirname(__FILE__) + '/error')
6
6
  require File.expand_path(File.dirname(__FILE__) + '/configure')
7
7
  require File.expand_path(File.dirname(__FILE__) + '/active_support')
@@ -146,9 +146,17 @@ module Timezone
146
146
 
147
147
  def timezone_id lat, lon #:nodoc:
148
148
  begin
149
- response = Net::HTTP.get(Timezone::Configure.url, "/timezoneJSON?lat=#{lat}&lng=#{lon}&username=#{Timezone::Configure.username}")
150
- JSON.parse(response)['timezoneId']
151
- rescue Exception => e
149
+ response = http_client.get("/timezoneJSON?lat=#{lat}&lng=#{lon}&username=#{Timezone::Configure.username}")
150
+ return nil unless response.code =~ /^2\d\d$/
151
+
152
+ data = JSON.parse(response.body)
153
+
154
+ if data['status'] && data['status']['value'] == 18
155
+ raise Timezone::Error::GeoNames, "api limit reached"
156
+ end
157
+
158
+ return data['timezoneId']
159
+ rescue => e
152
160
  raise Timezone::Error::GeoNames, e.message
153
161
  end
154
162
  end
@@ -161,5 +169,11 @@ module Timezone
161
169
  end
162
170
  end
163
171
 
172
+ private
173
+
174
+ def http_client #:nodoc:
175
+ @http_client ||= Timezone::Configure.http_client.new(
176
+ Timezone::Configure.protocol, Timezone::Configure.url)
177
+ end
164
178
  end
165
179
  end
@@ -0,0 +1 @@
1
+ {"status":{"message":"the daily limit of 30000 credits for XXXXX has been exceeded. Please throttle your requests or use the commercial service.","value":18}}
@@ -0,0 +1 @@
1
+ {"time":"2013-10-29 15:30","countryName":"Australia","sunset":"2013-10-30 19:42","rawOffset":9.5,"dstOffset":9.5,"countryCode":"AU","gmtOffset":10.5,"lng":138.477041423321,"sunrise":"2013-10-30 06:17","timezoneId":"Australia/Adelaide","lat":-34.92771808058}
@@ -1,6 +1,7 @@
1
1
  require 'timezone'
2
2
  require 'timezone/zone'
3
3
  require 'test/unit'
4
+ require "mocha/setup"
4
5
  require 'timecop'
5
6
 
6
7
  class TimezoneTest < Test::Unit::TestCase
@@ -137,12 +138,48 @@ class TimezoneTest < Test::Unit::TestCase
137
138
  assert_equal local.to_i, timezone.time(utc).to_i
138
139
  end
139
140
 
141
+ class HTTPTestClient
142
+ class << self ; attr_accessor :body ; end
143
+
144
+ Response = Struct.new(:body) do
145
+ def code ; '200' ; end
146
+ end
147
+
148
+ def initialize(protocol, host)
149
+ end
150
+
151
+ def get(url)
152
+ HTTPTestClient::Response.new(self.class.body)
153
+ end
154
+ end
155
+
140
156
  def test_using_lat_lon_coordinates
141
- Timezone::Configure.begin { |c| c.username = 'timezone' }
157
+ mock_path = File.expand_path(File.join(File.dirname(__FILE__), 'mocks'))
158
+ HTTPTestClient.body = File.open(mock_path + '/lat_lon_coords.txt').read
159
+
160
+ Timezone::Configure.begin do |c|
161
+ c.http_client = HTTPTestClient
162
+ c.username = 'timezone'
163
+ end
164
+
142
165
  timezone = Timezone::Zone.new :latlon => [-34.92771808058, 138.477041423321]
143
166
  assert_equal 'Australia/Adelaide', timezone.zone
144
167
  end
145
168
 
169
+ def test_api_limit_read_lat_lon_coordinates
170
+ mock_path = File.expand_path(File.join(File.dirname(__FILE__), 'mocks'))
171
+ HTTPTestClient.body = File.open(mock_path + '/api_limit_reached.txt').read
172
+
173
+ Timezone::Configure.begin do |c|
174
+ c.http_client = HTTPTestClient
175
+ c.username = 'timezone'
176
+ end
177
+
178
+ assert_raise Timezone::Error::GeoNames, 'api limit reached' do
179
+ Timezone::Zone.new :latlon => [-34.92771808058, 138.477041423321]
180
+ end
181
+ end
182
+
146
183
  def test_australian_timezone_with_dst
147
184
  timezone = Timezone::Zone.new :zone => 'Australia/Adelaide'
148
185
  utc = Time.utc(2010, 12, 23, 19, 37, 15)
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = "http://github.com/panthomakos/timezone"
12
12
  s.summary = "timezone-#{Timezone::VERSION}"
13
13
  s.description = %q{A simple way to get accurate current and historical timezone information based on zone or latitude and longitude coordinates. This gem uses the tz database (http://www.twinsun.com/tz/tz-link.htm) for historical timezone information. It also uses the geonames API for timezone latitude and longitude lookup (http://www.geonames.org/export/web-services.html).}
14
+ s.license = 'MIT'
14
15
 
15
16
  s.rubyforge_project = "timezone"
16
17
 
@@ -24,4 +25,5 @@ Gem::Specification.new do |s|
24
25
  s.add_development_dependency('rake')
25
26
  s.add_development_dependency('minitest', '~> 4.0')
26
27
  s.add_development_dependency('timecop')
28
+ s.add_development_dependency('mocha')
27
29
  end
metadata CHANGED
@@ -1,36 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timezone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
5
- prerelease:
4
+ version: 0.3.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Pan Thomakos
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-10-21 00:00:00.000000000 Z
11
+ date: 2014-04-15 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: minitest
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,17 +41,29 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: timecop
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
60
67
  - !ruby/object:Gem::Version
61
68
  version: '0'
62
69
  description: A simple way to get accurate current and historical timezone information
@@ -550,6 +557,7 @@ files:
550
557
  - lib/timezone/active_support.rb
551
558
  - lib/timezone/configure.rb
552
559
  - lib/timezone/error.rb
560
+ - lib/timezone/net_http_client.rb
553
561
  - lib/timezone/parser.rb
554
562
  - lib/timezone/parser/data.rb
555
563
  - lib/timezone/parser/link.rb
@@ -565,6 +573,8 @@ files:
565
573
  - lib/timezone/zone.rb
566
574
  - test/data/Helsinki_rules_without_timestamps.json
567
575
  - test/data/asia
576
+ - test/mocks/api_limit_reached.txt
577
+ - test/mocks/lat_lon_coords.txt
568
578
  - test/timezone/parser/rule/on_rules_test.rb
569
579
  - test/timezone/parser/rule_test.rb
570
580
  - test/timezone/parser/zone/data_generator_test.rb
@@ -574,33 +584,35 @@ files:
574
584
  - test/timezone_test.rb
575
585
  - timezone.gemspec
576
586
  homepage: http://github.com/panthomakos/timezone
577
- licenses: []
587
+ licenses:
588
+ - MIT
589
+ metadata: {}
578
590
  post_install_message:
579
591
  rdoc_options:
580
592
  - --charset=UTF-8
581
593
  require_paths:
582
594
  - lib
583
595
  required_ruby_version: !ruby/object:Gem::Requirement
584
- none: false
585
596
  requirements:
586
- - - ! '>='
597
+ - - '>='
587
598
  - !ruby/object:Gem::Version
588
599
  version: '0'
589
600
  required_rubygems_version: !ruby/object:Gem::Requirement
590
- none: false
591
601
  requirements:
592
- - - ! '>='
602
+ - - '>='
593
603
  - !ruby/object:Gem::Version
594
604
  version: '0'
595
605
  requirements: []
596
606
  rubyforge_project: timezone
597
- rubygems_version: 1.8.23
607
+ rubygems_version: 2.0.14
598
608
  signing_key:
599
- specification_version: 3
600
- summary: timezone-0.3.1
609
+ specification_version: 4
610
+ summary: timezone-0.3.2
601
611
  test_files:
602
612
  - test/data/Helsinki_rules_without_timestamps.json
603
613
  - test/data/asia
614
+ - test/mocks/api_limit_reached.txt
615
+ - test/mocks/lat_lon_coords.txt
604
616
  - test/timezone/parser/rule/on_rules_test.rb
605
617
  - test/timezone/parser/rule_test.rb
606
618
  - test/timezone/parser/zone/data_generator_test.rb