time_jawn 1.0.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 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