worldtimeengine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ [[Copyright]] (c) 2012 Nikita Fedyashev
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ ![travis-ci](http://travis-ci.org/nfedyashev/worldtimeengine.png)
2
+
3
+ # The WorldTimeEngine.com Ruby gem
4
+
5
+ Convert any IP address to current local time.
6
+
7
+ http://worldtimeengine.com/api/ip
8
+
9
+ ### Installation
10
+
11
+ Install the gem:
12
+
13
+ ``` bash
14
+ $ gem install worldtimeengine
15
+ ```
16
+
17
+ Add it to your Gemfile:
18
+
19
+ ``` ruby
20
+ gem 'worldtimeengine'
21
+ ```
22
+
23
+ ### Configuration
24
+
25
+ WorldTimeEngine.configure do |config|
26
+ config.api_key = YOUR_API_KEY
27
+ end
28
+
29
+
30
+ ### Synopsis
31
+
32
+ response = WorldTimeEngine.api('193.174.32.100')
33
+
34
+ response.version
35
+ => '1.1'
36
+ response.location.region
37
+ => 'Germany'
38
+ response.location.latitude
39
+ => 53.25
40
+ response.location.longitude
41
+ => 10.4
42
+
43
+ response.time.utc
44
+ => 2012-08-25 14:10:29 UTC
45
+ response.time.local
46
+ => 2012-08-25 16:10:29 +0200
47
+
48
+ response.time.zone.has_dst
49
+ => true
50
+ response.time.zone.current.abbreviation
51
+ => "CEST"
52
+ response.time.zone.current.description
53
+ => "Central European Summer Time"
54
+ response.time.zone.current.utc_offset
55
+ => '+2:00'
56
+ response.time.zone.current.is_dst
57
+ => true
58
+ response.time.zone.current.effective_until
59
+ => 2012-10-28 03:00:00 +0200
60
+
61
+ response.time.zone.next.abbreviation
62
+ => 'CET'
63
+ response.time.zone.next.description
64
+ => "Central European Time"
65
+ response.time.zone.next.utc_offset
66
+ => "+1:00"
67
+ response.time.zone.next.is_dst
68
+ => false
69
+ response.time.zone.next.effective_until
70
+ => 2013-03-31 02:00:00 +0100
71
+
72
+
73
+ ## Copyright
74
+ Copyright (c) 2012 Nikita Fedyashev.
75
+ See [LICENSE][] for details.
76
+
77
+ [license]: https://github.com/nfedyashev/worldtimeengine/blob/master/LICENSE.md
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
@@ -0,0 +1,29 @@
1
+ require 'worldtimeengine/client'
2
+ require 'worldtimeengine/configurable'
3
+
4
+ module WorldTimeEngine
5
+ class << self
6
+ include WorldTimeEngine::Configurable
7
+
8
+ # Delegate to a WorldTimeEngine::Client
9
+ #
10
+ # @return [WorldTimeEngine::Client]
11
+ def client
12
+ if @client
13
+ @client
14
+ else
15
+ @client = WorldTimeEngine::Client.new(options)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def method_missing(method_name, *args, &block)
22
+ return super unless client.respond_to?(method_name)
23
+ client.send(method_name, *args, &block)
24
+ end
25
+
26
+ end
27
+ end
28
+
29
+ WorldTimeEngine.setup
@@ -0,0 +1,59 @@
1
+ require 'httparty'
2
+ require 'hashie'
3
+ require 'worldtimeengine/configurable'
4
+
5
+ module WorldTimeEngine
6
+ # Wrapper for the WorldTimeEngine API
7
+ class Client
8
+ #include WorldTimeEngine::API
9
+ include WorldTimeEngine::Configurable
10
+
11
+ # Initializes a new Client object
12
+ #
13
+ # @return [WorldTimeEngine::Client]
14
+ def initialize(options={})
15
+ end
16
+
17
+ # Perform an HTTP GET request
18
+ def get(path, params={}, options={})
19
+ request(:get, path, params, options)
20
+ end
21
+
22
+ def api(ip)
23
+ endpoint = WorldTimeEngine.instance_variable_get(:@endpoint)
24
+ api_key = WorldTimeEngine.instance_variable_get(:@api_key)
25
+
26
+ timezone_hash = HTTParty.get("#{endpoint}/api/ip/#{api_key}/#{ip}", :format => :xml).to_hash['timezone']
27
+ timezone_hash.delete('xmlns:xsi')
28
+ timezone_hash.delete('xsi:noNamespaceSchemaLocation')
29
+
30
+ Hashie::Mash.new(timezone_hash).tap do |mash|
31
+ mash.time.utc = Time.parse "#{mash.time.utc} UTC"
32
+ mash.time.local = Time.parse "#{mash.time.local} #{mash.time.zone.current.abbreviation} #{mash.time.zone.current.utcoffset}"
33
+
34
+ mash.location.latitude = mash.location.latitude.to_f
35
+ mash.location.longitude = mash.location.longitude.to_f
36
+
37
+ mash.time.zone.has_dst = to_boolean mash.time.zone.hasDST
38
+
39
+ mash.time.zone.current.is_dst = to_boolean mash.time.zone.current.isdst
40
+ mash.time.zone.current.utc_offset = mash.time.zone.current.utcoffset
41
+ mash.time.zone.current.effective_until = Time.parse "#{mash.time.zone.current.effectiveUntil} #{mash.time.zone.current.abbreviation} #{mash.time.zone.current.utcoffset}"
42
+
43
+ mash.time.zone.next.is_dst = to_boolean mash.time.zone.next.isdst
44
+ mash.time.zone.next.utc_offset = mash.time.zone.next.utcoffset
45
+ mash.time.zone.next.effective_until = Time.parse "#{mash.time.zone.next.effectiveUntil} #{mash.time.zone.next.abbreviation} #{mash.time.zone.next.utcoffset}"
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def to_time(string)
52
+ Time.parse string
53
+ end
54
+
55
+ def to_boolean(string)
56
+ string == 'true' ? true : false
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,47 @@
1
+ module WorldTimeEngine
2
+ module Configurable
3
+ attr_writer :api_key
4
+ attr_accessor :endpoint
5
+
6
+ class << self
7
+
8
+ def keys
9
+ @keys ||= [
10
+ :api_key,
11
+ :endpoint
12
+ ]
13
+ end
14
+
15
+ end
16
+
17
+ # Convenience method to allow configuration options to be set in a block
18
+ def configure
19
+ yield self
20
+ self
21
+ end
22
+
23
+ # @return [Boolean]
24
+ def credentials?
25
+ credentials.values.all?
26
+ end
27
+
28
+ def reset!
29
+ @api_key = nil
30
+ @endpoint = 'http://worldtimeengine.com'
31
+ self
32
+ end
33
+ alias setup reset!
34
+
35
+ private
36
+
37
+ # @return [Hash]
38
+ def credentials
39
+ { :api_key => @api_key }
40
+ end
41
+
42
+ # @return [Hash]
43
+ def options
44
+ Hash[WorldTimeEngine::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <timezone xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://worldtimeengine.com/timezone.xsd">
3
+ <version>1.1</version>
4
+ <location>
5
+ <region>Germany</region>
6
+ <latitude>53.25</latitude>
7
+ <longitude>10.4</longitude>
8
+ </location>
9
+ <time>
10
+ <utc>2012-08-25 14:10:29</utc>
11
+ <local>2012-08-25 16:10:29</local>
12
+ <zone>
13
+ <hasDST>true</hasDST>
14
+ <current>
15
+ <abbreviation>CEST</abbreviation>
16
+ <description>Central European Summer Time</description>
17
+ <utcoffset>+2:00</utcoffset>
18
+ <isdst>true</isdst>
19
+ <effectiveUntil>2012-10-28 03:00:00</effectiveUntil>
20
+ </current>
21
+ <next>
22
+ <abbreviation>CET</abbreviation>
23
+ <description>Central European Time</description>
24
+ <utcoffset>+1:00</utcoffset>
25
+ <isdst>false</isdst>
26
+ <effectiveUntil>2013-03-31 02:00:00</effectiveUntil>
27
+ </next>
28
+ </zone>
29
+ </time>
30
+ </timezone>
@@ -0,0 +1,22 @@
1
+ curl http://worldtimeengine.com/api/ip/83c2bd05ec9bb21904cd8195ff93db/212.154.168.243
2
+ <?xml version="1.0" encoding="UTF-8" ?>
3
+ <timezone xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://worldtimeengine.com/timezone.xsd">
4
+ <version>1.1</version>
5
+ <location>
6
+ <region>Kazakhstan</region>
7
+ <latitude>51.1811</latitude>
8
+ <longitude>71.4278</longitude>
9
+ </location>
10
+ <time>
11
+ <utc>2012-08-25 18:14:04</utc>
12
+ <local>2012-08-26 00:14:04</local>
13
+ <zone>
14
+ <hasDST>false</hasDST>
15
+ <current>
16
+ <abbreviation>ALMT</abbreviation>
17
+ <description>Alma-Ata Mean Time</description>
18
+ <utcoffset>+6:00</utcoffset>
19
+ </current>
20
+ </zone>
21
+ </time>
22
+ </timezone>
@@ -0,0 +1,31 @@
1
+ curl http://worldtimeengine.com/api/ip/83c2bd05ec9bb21904cd8195ff93db/98.138.253.109
2
+ <?xml version="1.0" encoding="UTF-8" ?>
3
+ <timezone xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://worldtimeengine.com/timezone.xsd">
4
+ <version>1.1</version>
5
+ <location>
6
+ <region>United States</region>
7
+ <latitude>37.4249</latitude>
8
+ <longitude>-122.0074</longitude>
9
+ </location>
10
+ <time>
11
+ <utc>2012-08-25 18:15:50</utc>
12
+ <local>2012-08-25 11:15:50</local>
13
+ <zone>
14
+ <hasDST>true</hasDST>
15
+ <current>
16
+ <abbreviation>PDT</abbreviation>
17
+ <description>Pacific Daylight Time</description>
18
+ <utcoffset>-7:00</utcoffset>
19
+ <isdst>true</isdst>
20
+ <effectiveUntil>2012-11-04 02:00:00</effectiveUntil>
21
+ </current>
22
+ <next>
23
+ <abbreviation>PST</abbreviation>
24
+ <description>Pacific Standard Time</description>
25
+ <utcoffset>-8:00</utcoffset>
26
+ <isdst>false</isdst>
27
+ <effectiveUntil>2013-03-10 02:00:00</effectiveUntil>
28
+ </next>
29
+ </zone>
30
+ </time>
31
+ </timezone>
data/spec/helper.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'worldtimeengine'
2
+ require 'rspec'
3
+ require 'webmock/rspec'
4
+ require 'pry'
5
+
6
+ def a_get(path, endpoint='http://worldtimeengine.com')
7
+ a_request(:get, endpoint + path)
8
+ end
9
+
10
+ def stub_get(path, endpoint='http://worldtimeengine.com')
11
+ stub_request(:get, endpoint + path)
12
+ end
13
+
14
+ def fixture_path
15
+ File.expand_path("../fixtures", __FILE__)
16
+ end
17
+
18
+ def fixture(file)
19
+ File.new(fixture_path + '/' + file)
20
+ end
@@ -0,0 +1,78 @@
1
+ require 'helper'
2
+
3
+ describe WorldTimeEngine do
4
+ after do
5
+ WorldTimeEngine.reset!
6
+ end
7
+
8
+ describe "delegating to a client" do
9
+ before do
10
+ WorldTimeEngine.configure do |config|
11
+ config.api_key = 'abc'
12
+ end
13
+
14
+ stub_request(:get, "http://worldtimeengine.com/api/ip/abc/193.174.32.100").
15
+ to_return(:status => 200, :body => fixture('193.174.32.100.xml'), :headers => {})
16
+ end
17
+
18
+ it "requests the correct resource" do
19
+ WorldTimeEngine.api('193.174.32.100')
20
+
21
+ a_get("/api/ip/abc/193.174.32.100").should have_been_made
22
+ end
23
+
24
+ it "returns needed values" do
25
+ response = WorldTimeEngine.api('193.174.32.100')
26
+
27
+ response.version.should == '1.1'
28
+ response.location.region.should == 'Germany'
29
+ response.location.latitude.should == 53.25
30
+ response.location.longitude.should == 10.4
31
+
32
+ response.time.utc.should == Time.parse("2012-08-25 14:10:29 UTC")
33
+ response.time.local.should == Time.parse("2012-08-25 16:10:29")
34
+
35
+ response.time.zone.has_dst.should == true
36
+ response.time.zone.current.abbreviation.should == "CEST"
37
+ response.time.zone.current.description.should == "Central European Summer Time"
38
+ response.time.zone.current.utc_offset.should == '+2:00'
39
+ response.time.zone.current.is_dst.should == true
40
+ response.time.zone.current.effective_until.should == Time.parse("2012-10-28 03:00:00")
41
+
42
+ response.time.zone.next.abbreviation.should == 'CET'
43
+ response.time.zone.next.description.should == "Central European Time"
44
+ response.time.zone.next.utc_offset.should == "+1:00"
45
+ response.time.zone.next.is_dst.should == false
46
+ response.time.zone.next.effective_until.should == Time.parse("2013-03-31 02:00:00")
47
+ end
48
+ end
49
+
50
+ describe ".client" do
51
+ it "returns a WorldTimeEngine::Client" do
52
+ WorldTimeEngine.client.should be_a WorldTimeEngine::Client
53
+ end
54
+ end
55
+
56
+ describe ".configure" do
57
+ it "sets the api_key" do
58
+ WorldTimeEngine.configure do |config|
59
+ config.api_key = 'abc'
60
+ end
61
+ WorldTimeEngine.instance_variable_get(:@api_key).should eq 'abc'
62
+ end
63
+ end
64
+
65
+ describe ".credentials?" do
66
+ it "returns true if all credentials are present" do
67
+ WorldTimeEngine.configure do |config|
68
+ config.api_key = 'CK'
69
+ end
70
+ WorldTimeEngine.credentials?.should be_true
71
+ end
72
+ it "returns false if any credentials are missing" do
73
+ WorldTimeEngine.configure do |config|
74
+ end
75
+ WorldTimeEngine.credentials?.should be_false
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.add_dependency 'hashie'
5
+ gem.add_dependency 'httparty'
6
+ gem.add_development_dependency 'pry'
7
+ gem.add_development_dependency 'rake'
8
+ gem.add_development_dependency 'rspec'
9
+ gem.add_development_dependency 'webmock'
10
+ gem.authors = ["Nikita Fedyashev"]
11
+ gem.description = %q{A Ruby wrapper for the WorldTimeEngine.com API.}
12
+ gem.email = ['nfedyashev@gmail.com']
13
+ gem.files = %w(LICENSE.md README.md Rakefile worldtimeengine.gemspec)
14
+ gem.files += Dir.glob("lib/**/*.rb")
15
+ gem.files += Dir.glob("spec/**/*")
16
+ gem.homepage = 'https://github.com/nfedyashev/worldtimeengine'
17
+ gem.name = 'worldtimeengine'
18
+ gem.require_paths = ['lib']
19
+ gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')
20
+ gem.summary = %q{WorldTimeEngine API wrapper}
21
+ gem.test_files = Dir.glob("spec/**/*")
22
+ gem.version = '0.0.1'
23
+ end
24
+
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: worldtimeengine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nikita Fedyashev
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hashie
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: httparty
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: pry
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: webmock
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: A Ruby wrapper for the WorldTimeEngine.com API.
111
+ email:
112
+ - nfedyashev@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - LICENSE.md
118
+ - README.md
119
+ - Rakefile
120
+ - worldtimeengine.gemspec
121
+ - lib/worldtimeengine/client.rb
122
+ - lib/worldtimeengine/configurable.rb
123
+ - lib/worldtimeengine.rb
124
+ - spec/fixtures/193.174.32.100.xml
125
+ - spec/fixtures/another.xml
126
+ - spec/fixtures/us.xml
127
+ - spec/helper.rb
128
+ - spec/worldtimeengine_spec.rb
129
+ homepage: https://github.com/nfedyashev/worldtimeengine
130
+ licenses: []
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ segments:
142
+ - 0
143
+ hash: -4077128795819690830
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: 1.3.6
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: WorldTimeEngine API wrapper
156
+ test_files:
157
+ - spec/fixtures/193.174.32.100.xml
158
+ - spec/fixtures/another.xml
159
+ - spec/fixtures/us.xml
160
+ - spec/helper.rb
161
+ - spec/worldtimeengine_spec.rb