time_jawn 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Njg1YjFmZmFjMTA0M2E2Y2JjZjAwN2NiZGVhOGMwNDRjMzAzZmFjNg==
5
+ data.tar.gz: !binary |-
6
+ MzgyMjcxMzY3NGM0YTg3ZGQ5ZWZlODUwNzRhMWQ1NzYzOWI4NjA3ZQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YTIxNGVjZmJlOTA4NTJhOTYxOTRmYzA0OTA3ODBkYWEzMjQ3MTdiMzdlODNi
10
+ ODY1MDI5MjBkNjdkMTBkMjc5ZWM0OGFkOWIyZDU0MjBhYjNmYzQ5NTBjYjEz
11
+ MDk1ZjM3ZGNkYzhmNDVhYzljNTFjMGQzN2E5ODZiOWNiYTA2MGY=
12
+ data.tar.gz: !binary |-
13
+ NjAxMDc4ZTM0ZGJmZDUyNTJkNTE5MjM1M2Q2OGRhYjU1Mzg4OGQ0NjllNzY5
14
+ Yzk1ZTc0YTQ5MDRkMWY1YTRhYjEwOGE3YWY1NzczNzQ5ZGU5ZTAwZmEzZGJh
15
+ ZjRiYzc5NmRkYmIwMTU2ODcwZDJhOTM4ODNjYWUzODAwMjg3YjA=
@@ -0,0 +1,95 @@
1
+ # The base module of the TimeJawn gem. Everything in here assumes that your model has a valid time zone
2
+ # in a attribute name time_zone or has been delegating one to somewhere else.
3
+ module TimeJawn
4
+ # Automatically runs and adds ClassMethods to ActiveRecord::Base
5
+ def self.included(base)
6
+ base.send :extend, ClassMethods
7
+ end
8
+ # Defines methods that will attached to all ActiveRecord classes.
9
+ module ClassMethods
10
+ # When called it loads the methods located in InstanceMethods.
11
+ # It is typically included in a model's rb file so that instances of that class gain the InstanceMethods at each instantiation.
12
+ # class Event<ActiveRecord::Base
13
+ # has_time_zone
14
+ # end
15
+ def has_time_zone
16
+ send :include, InstanceMethods
17
+ end
18
+ # Locates all of an ActiveRecord class' DateTime Attributes and returns them as an array of symbols.
19
+ def _datetime_attributes
20
+ klass = self.name.constantize
21
+
22
+ datetime_attributes = []
23
+ klass.columns.each do |column|
24
+ datetime_attributes << column.name.to_sym if column.type == :datetime
25
+ end
26
+ return datetime_attributes
27
+ end
28
+ end
29
+ #Defines methods that will be added to instances of classes that have previously called has_time_zone.
30
+ module InstanceMethods
31
+ # This method generates a series of methods on instances. The methods that are created are called
32
+ # local_#{attribue} and local_#{attribute}= the attribute portion their names are completed by enumerating
33
+ # the datetime_attributes of the class. Twice as many methods as there are DateTime attributes will
34
+ # be created.
35
+ #
36
+ # :created_at, and :updated_at
37
+ #
38
+ # local_created_at
39
+ # local_updated_at
40
+ # local_created_at=
41
+ # local_updated_at=
42
+ #
43
+ # The local_#{attribue} methods will take the value stored in the attribute indicated by the methods name
44
+ # and apply a time zone conversion to it. This is useful for displaying the local time (according to the object).
45
+ #
46
+ # local_#{attribute}= methods are assignment shortcuts. They behave a little differently than you would expect.
47
+ # They do not take a local time and convert it into utc (or whatever, ActiveSupport will handle that for us),
48
+ # what these assigment methods do is take any sort of string that looks like a time, or any sort of time or datetime
49
+ # object lop off whatever timezone is being fed in and glue the instances local timezone on the end before applying
50
+ # it to the appropriate attribute. This is convenient for some one in one time zone setting a value for an instance
51
+ # that represents a different time zone. For example:
52
+ #
53
+ # I am in Philadelphia (EST), my application is set to UTC, and I want to set the time on an Alarm instance that
54
+ # goes off in San Francisco (PST). I want that time to be 6PM. In Philadlephia I choose 6PM (local), the applications assumes I
55
+ # meant 6PM UTC (2PM EST and 11AM PST). That is not what I intended, I intended on 6PM PST, and now my Alarm is all wrong.
56
+ # The assignment methods turn 6PM (set in EST, and processed in UTC) into 6PM PST (or 9PM EST, 1AM UTC) the expected time. The
57
+ # Alarm goes off as expected!*
58
+ #
59
+ # *Times in this example may be wrong since I put them in myself.
60
+ #
61
+ # You can see examples of how these methods work in the specs folder.
62
+ def self.included(base)
63
+ base._datetime_attributes.each do |attribute|
64
+ define_method(:"local_#{attribute}") { _to_local(send(attribute)) }
65
+ define_method(:"local_#{attribute}=") do |time_or_string_value|
66
+ if time_or_string_value.is_a? String
67
+ write_attribute(attribute, _add_zone(time_or_string_value))
68
+ else
69
+ write_attribute(attribute, _change_zone(time_or_string_value))
70
+ end
71
+ end
72
+ end
73
+ end
74
+ # Returns the current time according to the instance.
75
+ def current_time
76
+ _to_local(DateTime.current)
77
+ end
78
+ # converts a time object into it's local counter part (they will have the same value but differnt presentation.)
79
+ def _to_local(time)
80
+ time.in_time_zone(self.time_zone)
81
+ end
82
+
83
+ # Given a string that looks like a time. It will convert that string into a time object that matches the time but with
84
+ # the instances time zone appended.
85
+ def _add_zone(time_string)
86
+ Time.zone = self.time_zone
87
+ Time.zone.parse(time_string)
88
+ end
89
+
90
+ # Returns a string representation of a time object suitable for consumption by add_zone.
91
+ def _change_zone(time)
92
+ _add_zone(time.strftime('%a, %d %b %Y %H:%M:%S'))
93
+ end
94
+ end
95
+ end
data/lib/time_jawn.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'time_jawn/time_jawn'
2
+
3
+ ActiveRecord::Base.send(:include, TimeJawn)
@@ -0,0 +1,192 @@
1
+ require 'spec_helper'
2
+
3
+ describe Happening do
4
+ before(:each){
5
+ @happening1 = Happening.find_by_name('Eastern Time (US & Canada)')
6
+ @happening2 = Happening.find_by_name('Pacific/Honolulu')
7
+ Time.zone = 'UTC'
8
+ }
9
+ context 'class method' do
10
+ describe "datetime_attributes" do
11
+ it "returns an array of all datetime objects for the class" do
12
+ expect(Happening._datetime_attributes).to eq [:start_time, :created_at, :updated_at]
13
+ end
14
+ end
15
+ describe "has_time_zone" do
16
+ it "does not have instance methods until called" do
17
+ expect(Happening.instance_methods.include? :local_start_time).to eq false
18
+ expect(Happening.instance_methods.include? :local_created_at).to eq false
19
+ expect(Happening.instance_methods.include? :local_updated_at).to eq false
20
+ expect(Happening.instance_methods.include? :local_start_time=).to eq false
21
+ expect(Happening.instance_methods.include? :local_updated_at=).to eq false
22
+ expect(Happening.instance_methods.include? :local_updated_at=).to eq false
23
+ end
24
+ it "has instance methods once called " do
25
+
26
+ Happening.has_time_zone
27
+
28
+ expect(Happening.instance_methods.include? :local_start_time).to eq true
29
+ expect(Happening.instance_methods.include? :local_created_at).to eq true
30
+ expect(Happening.instance_methods.include? :local_updated_at).to eq true
31
+ expect(Happening.instance_methods.include? :local_start_time=).to eq true
32
+ expect(Happening.instance_methods.include? :local_created_at=).to eq true
33
+ expect(Happening.instance_methods.include? :local_updated_at=).to eq true
34
+ end
35
+ end
36
+ end
37
+ context 'static instance methods' do
38
+
39
+ describe "self.included(base)" do
40
+ pending "How do you test this? I suppose if the dynamic tests exist this worked. Seems shoddy."
41
+ end
42
+
43
+ describe "current_time" do
44
+ it "returns a time with zone object reflecting the current local time of the instance" do
45
+ Timecop.freeze
46
+ expect(DateTime.current).to eq @happening1.current_time
47
+ Timecop.return
48
+ end
49
+ end
50
+
51
+ describe "_to_local(time)" do
52
+ it "returns a time with zone that has been coverted to reflect the local time" do
53
+ expect(@happening1.start_time).to eq 'Mon, 01 Apr 2013 00:01:00 UTC +00:00'
54
+ expect(@happening1._to_local(@happening1.start_time)).to eq 'Sun, 31 Mar 2013 20:01:00 EDT -04:00'
55
+ expect(@happening1._to_local(@happening1.start_time).to_s).to eq "2013-03-31 20:01:00 -0400"
56
+ end
57
+ end
58
+
59
+ describe "_add_zone(time_string)" do
60
+ it "returns a time with zone object that reflects the time value passed in time_string with time zone information of instance appended" do
61
+ expect(@happening1._add_zone("2013-08-19 12:34:56")).to eq 'Mon, 19 Aug 2013 12:34:56 EDT -04:00'
62
+ expect(@happening2._add_zone("2013-08-19 12:34:56")).to eq 'Mon, 19 Aug 2013 12:34:56 HST -10:00'
63
+ expect(@happening1._add_zone("2013-11-11 12:34:56")).to eq 'Mon, 11 Nov 2013 12:34:56 EST -05:00'
64
+ expect(@happening2._add_zone("2013-11-11 12:34:56")).to eq 'Mon, 11 Nov 2013 12:34:56 HST -10:00'
65
+ end
66
+ end
67
+
68
+ describe "_change_zone(time)" do
69
+ it "returns a time with zone object that has had only it's time zone switched to local time of instance" do
70
+ Time.zone = 'Rangoon'
71
+ time = Time.zone.parse("Wed, 28 Aug 2015 15:16:16")
72
+ expect(time.to_s.split(' ')[2]).to eq ('+0630')
73
+ expect(time.to_s.split(' ')[2]).to_not eq ('-0400')
74
+ expect(@happening1._change_zone(time)).to_not eq time
75
+ expect(@happening1._change_zone(time).to_s.split(' ')[0]).to eq time.to_s.split(' ')[0]
76
+ expect(@happening1._change_zone(time).to_s.split(' ')[1]).to eq time.to_s.split(' ')[1]
77
+ expect(@happening1._change_zone(time).to_s.split(' ')[2]).to_not eq time.to_s.split(' ')[2]
78
+ expect(@happening1._change_zone(time).to_s.split(' ')[2]).to_not eq ('+0630')
79
+ expect(@happening1._change_zone(time).to_s.split(' ')[2]).to eq ('-0400')
80
+ end
81
+ end
82
+ end
83
+ context 'dynamic instance methods' do
84
+ describe "local_start_time" do
85
+ it "returns a time with zone object that reflects the value of start_time altered to the instance's time zone" do
86
+ expect(@happening1.start_time).to eq 'Mon, 01 Apr 2013 00:01:00 UTC +00:00'
87
+ expect(@happening1.start_time).to eq 'Sun, 31 Mar 2013 20:01:00 EDT -04:00'
88
+ Time.zone = 'Eastern Time (US & Canada)'
89
+ expect(@happening1.local_start_time.to_s).to eq "2013-03-31 20:01:00 -0400"
90
+
91
+ expect(@happening2.start_time).to eq 'Mon, 01 Apr 2013 00:00:00 UTC +00:00'
92
+ expect(@happening2.start_time).to eq 'Sun, 31 Mar 2013 14:00:00 HST -10:00'
93
+ Time.zone = 'Pacific/Honolulu'
94
+ expect(@happening2.local_start_time.to_s).to eq "2013-03-31 14:00:00 -1000"
95
+ end
96
+ end
97
+
98
+ describe "local_updated_at" do
99
+ it "returns a time with zone object that reflects the value of updated_at at altered to the instance's time zone" do
100
+ expect(@happening1.updated_at).to eq 'Tue, 01 Jan 2013 00:01:00 UTC +0000'
101
+ expect(@happening1.updated_at).to eq 'Wed, 31 Dec 2012 20:01:00 EDT -04:00'
102
+ Time.zone = 'Eastern Time (US & Canada)'
103
+ expect(@happening1.local_updated_at.to_s).to eq "2012-12-31 19:01:00 -0500"
104
+
105
+ expect(@happening2.updated_at).to eq 'Tue, 01 Jan 2013 00:00:00 UTC +0000'
106
+ expect(@happening2.updated_at).to eq 'Wed, 31 Dec 2012 14:00:00 HST -10:00'
107
+ Time.zone = 'Pacific/Honolulu'
108
+ expect(@happening2.local_updated_at.to_s).to eq "2012-12-31 14:00:00 -1000"
109
+ end
110
+ end
111
+
112
+ describe "local_created_at" do
113
+ it "returns a time with zone object that reflects the value of created_at at altered to the instance's time zone" do
114
+ expect(@happening1.created_at).to eq 'Tue, 01 Jan 2013 00:01:00 UTC +0000'
115
+ expect(@happening1.created_at).to eq 'Wed, 31 Dec 2012 20:01:00 EDT -04:00'
116
+ Time.zone = 'Eastern Time (US & Canada)'
117
+ expect(@happening1.local_created_at.to_s).to eq "2012-12-31 19:01:00 -0500"
118
+
119
+ expect(@happening2.created_at).to eq 'Tue, 01 Jan 2013 00:00:00 UTC +0000'
120
+ expect(@happening2.created_at).to eq 'Wed, 31 Dec 2012 14:00:00 HST -10:00'
121
+ Time.zone = 'Pacific/Honolulu'
122
+ expect(@happening2.local_created_at.to_s).to eq "2012-12-31 14:00:00 -1000"
123
+ end
124
+ end
125
+
126
+ describe "local_start_time=(time_or_string)" do
127
+ it "sets start_time on the instance to a time_with_zone object only modifying the time zone" do
128
+ expect(@happening1.start_time).to eq 'Mon, 01 Apr 2013 00:01:00 UTC +00:00'
129
+
130
+ @happening1.local_start_time = Time.parse("Thu, 29 Aug 2013 02:40:12 HST -10:00")
131
+ expect(@happening1.start_time).to eq Time.parse("2013-08-29 02:40:12 -0400")
132
+
133
+ @happening1.local_start_time = Time.parse("Thu, 29 Aug 2013 02:41:12")
134
+ expect(@happening1.start_time).to eq Time.parse("2013-08-29 02:41:12 -0400")
135
+
136
+ @happening1.local_start_time = "Thu, 29 Aug 2013 02:42:12"
137
+ expect(@happening1.start_time).to eq Time.parse("2013-08-29 02:42:12 -0400")
138
+
139
+ @happening1.local_start_time = "Thu, 29 Aug 2013 02:43:12 HST -10:00"
140
+ expect(@happening1.start_time).to eq Time.parse("2013-08-29 02:43:12 -0400")
141
+
142
+ @happening1.local_start_time = "2013-11-11 12:34:56"
143
+ expect(@happening1.start_time).to eq Time.parse("2013-11-11 12:34:56 -0500")
144
+
145
+ end
146
+ end
147
+
148
+ describe "local_updated_at=(time_or_string)" do
149
+ it "sets updated_at on the instance to a time_with_zone object only modifying the time zone" do
150
+ expect(@happening1.updated_at).to eq 'Tue, 01 Jan 2013 00:01:00 +0000'
151
+
152
+ @happening1.local_updated_at = Time.parse("Thu, 29 Aug 2013 02:40:12 HST -10:00")
153
+ expect(@happening1.updated_at).to eq Time.parse("2013-08-29 02:40:12 -0400")
154
+
155
+ @happening1.local_updated_at = Time.parse("Thu, 29 Aug 2013 02:41:12")
156
+ expect(@happening1.updated_at).to eq Time.parse("2013-08-29 02:41:12 -0400")
157
+
158
+ @happening1.local_updated_at = "Thu, 29 Aug 2013 02:42:12"
159
+ expect(@happening1.updated_at).to eq Time.parse("2013-08-29 02:42:12 -0400")
160
+
161
+ @happening1.local_updated_at = "Thu, 29 Aug 2013 02:43:12 HST -10:00"
162
+ expect(@happening1.updated_at).to eq Time.parse("2013-08-29 02:43:12 -0400")
163
+
164
+ @happening1.local_updated_at = "2013-11-11 12:34:56"
165
+ expect(@happening1.updated_at).to eq Time.parse("2013-11-11 12:34:56 -0500")
166
+
167
+ end
168
+ end
169
+
170
+ describe "local_created_at=(time_or_string)" do
171
+ it "sets created_at on the instance to a time_with_zone object only modifying the time zone" do
172
+ expect(@happening1.created_at).to eq ' Tue, 01 Jan 2013 00:01:00 +0000'
173
+
174
+ @happening1.local_created_at = Time.parse("Thu, 29 Aug 2013 02:40:12 HST -10:00")
175
+ expect(@happening1.created_at).to eq Time.parse("2013-08-29 02:40:12 -0400")
176
+
177
+ @happening1.local_created_at = Time.parse("Thu, 29 Aug 2013 02:41:12")
178
+ expect(@happening1.created_at).to eq Time.parse("2013-08-29 02:41:12 -0400")
179
+
180
+ @happening1.local_created_at = "Thu, 29 Aug 2013 02:42:12"
181
+ expect(@happening1.created_at).to eq Time.parse("2013-08-29 02:42:12 -0400")
182
+
183
+ @happening1.local_created_at = "Thu, 29 Aug 2013 02:43:12 HST -10:00"
184
+ expect(@happening1.created_at).to eq Time.parse("2013-08-29 02:43:12 -0400")
185
+
186
+ @happening1.local_created_at = "2013-11-11 12:34:56"
187
+ expect(@happening1.created_at).to eq Time.parse("2013-11-11 12:34:56 -0500")
188
+
189
+ end
190
+ end
191
+ end
192
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time_jawn
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Mark Platt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '3.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3-ruby
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
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: timecop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: TimeJawn makes class instances time zone aware. It doesn't care one iota
84
+ about system, application or database time as far as I can tell. It has some expectations
85
+ and adds some useful methods.
86
+ email: mplatt@tammantech.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - lib/time_jawn.rb
92
+ - lib/time_jawn/time_jawn.rb
93
+ - spec/time_jawn_spec.rb
94
+ homepage: http://tammantech.com
95
+ licenses:
96
+ - MIT
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: 1.9.3
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.0.7
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: TimeJawn makes time zone aware class instances.
118
+ test_files:
119
+ - spec/time_jawn_spec.rb