greenwich 0.0.5 → 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.
data/.gitignore CHANGED
@@ -1,4 +1,12 @@
1
1
  *.gem
2
+ *.rbc
2
3
  .bundle
4
+ .config
5
+ .yardoc
3
6
  Gemfile.lock
4
- pkg/*
7
+ _yardoc
8
+ coverage
9
+ lib/bundler/man
10
+ pkg
11
+ spec/reports
12
+ tmp
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm use --create ruby-1.9.2-p180@greenwich
1
+ rvm use --create ruby-1.9.3-p125@greenwich
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in greenwich.gemspec
3
+ gem 'rake'
4
+
4
5
  gemspec
6
+
data/README.md CHANGED
@@ -29,90 +29,95 @@ Initialization
29
29
 
30
30
  You add Greenwich to your models like so:
31
31
 
32
- date_with_time_zone :field_name
32
+ time_with_time_zone :your_column_name_utc
33
33
 
34
- Meta-Programming Magic
35
- --------------------------------
34
+ By default, Greenwich removes the `_utc` from the column name and uses
35
+ the resulting string as the composed field.
36
36
 
37
- By default Greenwich looks for a few different columns in your model depending on the
38
- field name you passed in. Let's look at some examples.
37
+ For example, the above call would result in a composed field called
38
+ `your_column_name`.
39
39
 
40
- **DateTime Field Lookup**
40
+ ### Time Zones ###
41
41
 
42
- Greenwich will lookup `:field_name` based on a couple different standard column suffixes.
42
+ Greenwich will try to use convention to choose a time zone column name
43
+ based on the time field you choose.
43
44
 
44
- * `_at`
45
- * `_datetime`
45
+ time_with_time_zone :started_at_utc
46
46
 
47
- For example, if you specify:
47
+ Will look for a column called `started_at_time_zone` which contains the
48
+ time zone for the time field.
48
49
 
49
- date_with_time_zone :start
50
+ #### Custom Time Zone ####
50
51
 
51
- Greenwich will look for the columns `start_at` and `start_datetime` (in that order).
52
+ If you want to use the same time zone for multiple time fields or just
53
+ don't like the custom one we choose for you, you can pass a `:time_zone`
54
+ option which will override our default.
52
55
 
53
- **Time Zone Field Lookup**
56
+ time_with_time_zone :started_at_utc, :time_zone => :started_at_zone
54
57
 
55
- Time Zone lookups default to a per-field or per-model specification. If you specify:
58
+ Will tell Greenwich that when the user accesses the `started_at` method,
59
+ it will use the information from the `started_at_zone` column for its
60
+ time zone.
56
61
 
57
- date_with_time_zone :start
62
+ ### Convention... but missing a little configuration ###
58
63
 
59
- Greenwich will lookup the time zone from `:start_time_zone` first, and if it doesn't
60
- find a field by that name, it will use `:time_zone`.
64
+ We're on `v1.0.0` and have more features planned in the future, however
65
+ for now, all columns passed to `time_with_time_zone` _must_ end in `_utc`.
61
66
 
62
67
  Usage
63
68
  --------------------------------
64
- * **Note:** _These examples assume the application's default time zone is set to UTC.
65
- If you have modified the default time zone, directly accessing your DateTime field
66
- will render it in _that_ time zone and not UTC._
69
+ **Note:** _These examples assume the application's default time zone is set to UTC.
70
+ If you have modified the default time zone, directly accessing your DateTime field
71
+ will render it in **that** time zone and not UTC._
67
72
 
68
73
  When working with your instances, Greenwich will convert to the proper time zone when
69
- you access it. So if you've previously saved a DateTime like this:
74
+ you access it. So if you've defined a Greenwich time field like this:
75
+
76
+ time_with_time_zone :started_at_utc
70
77
 
71
- my_model.start = Time.strptime('2011-07-04 13:00:00 -600 CST')
78
+ And if you've previously saved a DateTime like this:
79
+
80
+ my_model.started_at_utc = Time.utc(2011, 7, 4, 13, 0, 0)
81
+ my_model.started_at_time_zone = 'Alaska'
72
82
 
73
83
  Then that will result in your model returning the following values (assuming these
74
84
  particular columns exist in the database):
75
85
 
76
- my_model.start_at # => 2011-07-04 19:00:00 GMT
77
- my_model.start_datetime # => 2011-07-04 19:00:00 GMT
78
- my_model.start_time_zone # => 'Central Standard Time'
79
- my_model.time_zone # => 'Central Standard Time'
86
+ my_model.started_at_utc # => ActiveSupport::TimeWithZone 2011-07-04 13:00:00 UTC
87
+ my_model.started_at_time_zone # => ActiveSupport::TimeZone 'Alaska'
80
88
 
81
- Whereas asking Greenwich for the value of `start` will result in:
89
+ Whereas asking Greenwich for the value of `started_at` will result in:
82
90
 
83
- my_model.start # => 2011-07-04 13:00:00 CST
91
+ my_model.started_at # => ActiveSupport::TimeWithZone 2011-07-04 04:00:00 AKDT
84
92
 
85
93
  If you then change your time zone:
86
94
 
87
- my_model.start_time_zone = 'Eastern Standard Time'
95
+ my_model.started_at_time_zone = 'Hawaii'
88
96
 
89
97
  Then calling the attributes on your model will result in the following:
90
98
 
91
- my_model.start_at # => 2011-07-04 19:00:00 GMT
92
- my_model.start_datetime # => 2011-07-04 19:00:00 GMT
93
- my_model.start_time_zone # => 'Eastern Standard Time'
94
- my_model.time_zone # => 'Eastern Standard Time'
99
+ my_model.started_at_utc # => ActiveSupport::TimeWithZone 2011-07-04 13:00:00 UTC
100
+ my_model.started_at_time_zone # => ActiveSupport::TimeZone 'Hawaii'
95
101
 
96
- And again, asking Greenwich for the value of `start` will result in:
102
+ And again, asking Greenwich for the value of `started_at` will result in:
97
103
 
98
- my_model.start # => 2011-07-04 13:00:00 EST
104
+ my_model.started_at # => ActiveSupport::TimeWithZone 2011-07-04 03:00:00 HADT
99
105
 
100
106
  Issues
101
107
  ------
102
108
 
103
- If you have problems, please create a [Github issue](https://github.com/jfelchner/greenwich/issues).
109
+ If you have problems, please create a [Github issue](issues).
104
110
 
105
111
  Credits
106
112
  -------
107
113
 
108
- ![thekompanee](http://www.thekompanee.com/public_files/kompanee-github-readme-logo.png)
114
+ ![chirrpy](https://dl.dropbox.com/s/f9s2qd0kmbc8nwl/github_logo.png?dl=1)
109
115
 
110
- greenwich is maintained by [The Kompanee, Ltd.](http://www.thekompanee.com)
116
+ greenwich is maintained by [Chrrpy, LLC](http://chirrpy.com)
111
117
 
112
- The names and logos for The Kompanee are trademarks of The Kompanee, Ltd.
118
+ The names and logos for Chirrpy are trademarks of Chrrpy, LLC
113
119
 
114
120
  License
115
121
  -------
116
122
 
117
- greenwich is Copyright © 2011 The Kompanee. It is free software, and may be redistributed under the terms specified in the LICENSE file.
118
-
123
+ greenwich is Copyright © 2011 Chirrpy. It is free software, and may be redistributed under the terms specified in the LICENSE file.
data/Rakefile CHANGED
@@ -1 +1,2 @@
1
+ #!/usr/bin/env rake
1
2
  require 'bundler/gem_tasks'
data/greenwich.gemspec CHANGED
@@ -11,9 +11,9 @@ Gem::Specification.new do |s|
11
11
  s.version = Greenwich::VERSION
12
12
  s.platform = Gem::Platform::RUBY
13
13
 
14
- s.authors = ["thekompanee", "jfelchner"]
15
- s.email = ["support@thekompanee.com"]
16
- s.homepage = "http://github.com/jfelchner/greenwich"
14
+ s.authors = ["jfelchner", "m5rk"]
15
+ s.email = ["jeff+greenwich@chirrpy.com"]
16
+ s.homepage = "http://github.com/chirrpy/greenwich"
17
17
 
18
18
  s.summary = %q{Allowing users to select dates with custom time zones since 2011.}
19
19
  s.description = %q{Store all of your times in the database as UTC but want to give your users the ability to choose a custom time zone for each instance of a DateTime field?}
@@ -28,9 +28,13 @@ Gem::Specification.new do |s|
28
28
  s.require_paths = ["lib"]
29
29
  #= Manifest =#
30
30
 
31
- s.add_dependency('activerecord', '~> 3.0')
31
+ s.add_dependency('activerecord', '~> 3.0')
32
+ s.add_dependency('activesupport', '~> 3.0')
33
+ s.add_dependency('tzinfo', '~> 0.3')
32
34
 
33
35
  s.add_development_dependency('bundler', '~> 1.0')
34
36
  s.add_development_dependency('rspec', '~> 2.6')
35
37
  s.add_development_dependency('yard', '~> 0.7')
38
+ s.add_development_dependency('sqlite3', '~> 1.3')
39
+ s.add_development_dependency('pry')
36
40
  end
data/lib/greenwich.rb CHANGED
@@ -1,5 +1,7 @@
1
- require "greenwich/version"
2
- require "greenwich/utilities"
3
- require "greenwich/time_with_zone"
4
- require "greenwich/rails"
5
-
1
+ require 'tzinfo'
2
+ require 'active_record'
3
+ require 'active_support/all'
4
+ require 'greenwich/conversion'
5
+ require 'greenwich/time_zone'
6
+ require 'greenwich/utilities'
7
+ require 'greenwich/version'
@@ -0,0 +1,82 @@
1
+ module Greenwich
2
+ module Conversion
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def time_with_time_zone(utc_time_field, options = {})
7
+ time_field = utc_time_field.to_s.gsub /_utc$/, ''
8
+ time_zone_field = options[:time_zone] || "#{time_field}_time_zone"
9
+
10
+ class_eval do
11
+ columns_hash[time_field] = ActiveRecord::ConnectionAdapters::Column.new(time_field, nil, "datetime")
12
+ end
13
+
14
+ define_method "#{time_field}_utc=" do |value|
15
+ greenwich_time_fields_converted["#{time_field}_utc"] = true
16
+
17
+ super(value)
18
+ end
19
+
20
+ define_method time_field do
21
+ time_zone = Greenwich::Utilities.get_time_zone(self, time_zone_field)
22
+ time = read_attribute(utc_time_field)
23
+ time = time.in_time_zone(time_zone) if time && time_zone
24
+
25
+ time
26
+ end
27
+
28
+ define_method "#{time_field}=" do |value|
29
+ time_zone = Greenwich::Utilities.get_time_zone(self, time_zone_field)
30
+ time = Greenwich::Utilities.coerce_to_time_without_zone(value)
31
+ time = ActiveSupport::TimeWithZone.new(nil, time_zone, time) if time && time_zone
32
+
33
+ greenwich_time_fields_converted["#{time_field}_utc"] = true unless time_zone.nil?
34
+
35
+ write_attribute(utc_time_field, time)
36
+ end
37
+
38
+ time_zone time_zone_field.to_sym, :for => utc_time_field.to_sym
39
+ end
40
+
41
+ def time_zone(name, options = {})
42
+ associated_time_fields = Array.wrap(options[:for]).map {|f| f.to_s.gsub /_utc$/, ''}
43
+
44
+ define_method name do
45
+ time_zone_name = read_attribute(name)
46
+
47
+ Greenwich::Utilities.coerce_to_time_zone(time_zone_name)
48
+ end
49
+
50
+ define_method "#{name}=" do |value|
51
+ time_zone = Greenwich::Utilities.coerce_to_time_zone_name(value)
52
+ write_attribute(name, time_zone)
53
+
54
+ associated_time_fields.each do |time_field|
55
+ if greenwich_time_field_needs_conversion?(time_field, name)
56
+ send("#{time_field}=".to_sym, read_attribute("#{time_field}_utc"))
57
+
58
+ greenwich_time_fields_converted["#{time_field}_utc"] = true
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def greenwich_time_fields_converted
66
+ @greenwich_time_fields_converted ||= {}
67
+ end
68
+
69
+ def greenwich_time_fields_converted=(value)
70
+ @greenwich_time_fields_converted = value
71
+ end
72
+
73
+ private
74
+ def greenwich_time_field_needs_conversion?(time_field, time_zone_field)
75
+ (send("#{time_zone_field}_was".to_sym).nil? || send("#{time_field}_utc_was").nil?) &&
76
+ read_attribute("#{time_field}_utc").present? &&
77
+ self.greenwich_time_fields_converted["#{time_field}_utc"].nil?
78
+ end
79
+ end
80
+ end
81
+
82
+ ActiveRecord::Base.send :include, Greenwich::Conversion
@@ -0,0 +1,7 @@
1
+ module ActiveSupport
2
+ class TimeZone
3
+ def to_s
4
+ name
5
+ end
6
+ end
7
+ end
@@ -6,22 +6,34 @@ module Greenwich
6
6
  get_target_column(target_columns, columns)
7
7
  end
8
8
 
9
- def self.get_time_field(name, columns)
10
- target_columns = ["#{name}_at", "#{name}_datetime", "#{name}_time"]
9
+ def self.get_time_zone(object, time_zone_field_name)
10
+ begin
11
+ time_zone_name = object.send(time_zone_field_name.to_sym)
12
+ rescue
13
+ time_zone_name = ''
14
+ end
11
15
 
12
- get_target_column(target_columns, columns)
16
+ Greenwich::Utilities.coerce_to_time_zone(time_zone_name)
13
17
  end
14
18
 
15
- def self.get_time_zone_from(value)
16
- return nil if [nil, ''].include? value
19
+ def self.coerce_to_time_zone(value)
20
+ return nil if value.nil?
21
+ return value if value.is_a? ActiveSupport::TimeZone
17
22
 
18
- begin
19
- value = ActiveSupport::TimeZone.new(value) unless value.is_a? ActiveSupport::TimeZone
20
- rescue ArgumentError
21
- raise ArgumentError, "'#{value}' cannot be converted into a TimeZone."
22
- end
23
+ ActiveSupport::TimeZone.new(value)
24
+ end
25
+
26
+ def self.coerce_to_time_zone_name(value)
27
+ coerce_to_time_zone(value).try(:name)
28
+ end
23
29
 
24
- value
30
+ def self.coerce_to_time_without_zone(value)
31
+ return value if value.is_a?(Time)
32
+
33
+ value.gsub! /\s[-+]\d{4}$/, '' if value.respond_to? :gsub!
34
+ value.to_time if value.respond_to? :to_time
35
+ rescue ArgumentError
36
+ nil
25
37
  end
26
38
 
27
39
  private
@@ -1,3 +1,3 @@
1
1
  module Greenwich
2
- VERSION = "0.0.5"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,313 @@
1
+ require 'spec_helper'
2
+ require 'pry'
3
+
4
+ root = File.expand_path(File.join(File.dirname(__FILE__), '../..'))
5
+ db_root = File.join(root, 'db')
6
+
7
+ Dir.mkdir(db_root) unless File.exists?(db_root)
8
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3',
9
+ :database => "#{db_root}/conversion.db")
10
+
11
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'model_with_time_zones'")
12
+ ActiveRecord::Base.connection.create_table(:model_with_time_zones) do |t|
13
+ t.datetime :started_at_utc
14
+ t.datetime :ended_at_utc
15
+ t.string :time_zone
16
+ end
17
+
18
+ class ModelWithTimeZone < ActiveRecord::Base
19
+ include Greenwich::Conversion
20
+
21
+ attr_accessible :started_at_utc,
22
+ :ended_at_utc,
23
+ :time_zone
24
+
25
+ time_with_time_zone :started_at_utc, :time_zone => :time_zone
26
+ time_with_time_zone :ended_at_utc, :time_zone => :time_zone
27
+
28
+ time_zone :time_zone, :for => [:started_at_utc, :ended_at_utc]
29
+ end
30
+
31
+ describe Greenwich::Conversion do
32
+ describe '.time_with_time_zone' do
33
+ let(:model) { ModelWithTimeZone.new }
34
+ let(:alaskan_time_zone) { ActiveSupport::TimeZone.new('Alaska') }
35
+
36
+ describe '.columns_hash' do
37
+ it 'adds the virtual column to the columns_hash for the time field' do
38
+ ModelWithTimeZone.columns_hash.keys.should include 'started_at'
39
+ end
40
+
41
+ it 'adds the virtual column with a `datetime` type' do
42
+ ModelWithTimeZone.columns_hash['started_at'].type.should eql :datetime
43
+ end
44
+ end
45
+
46
+ describe '#time_field_utc=' do
47
+ let(:model) { ModelWithTimeZone.new }
48
+ let(:alaskan_time_zone) { ActiveSupport::TimeZone.new('Alaska') }
49
+ let(:raw_time_field) { model.send(:read_attribute, :started_at_utc) }
50
+
51
+ context 'when the time field is set via the writer' do
52
+ before { model.started_at_utc = Time.utc(2012, 1, 2, 12, 59, 1) }
53
+
54
+ it 'is not changed' do
55
+ raw_time_field.should eql Time.utc(2012, 1, 2, 12, 59, 1)
56
+ end
57
+
58
+ it 'is not eligible for conversion' do
59
+ model.send(:greenwich_time_field_needs_conversion?, 'started_at', 'time_zone').should be_false
60
+ end
61
+
62
+ context 'and the time zone is subsequently set' do
63
+ before { model.time_zone = alaskan_time_zone }
64
+
65
+ it 'is not changed' do
66
+ raw_time_field.should eql Time.utc(2012, 1, 2, 12, 59, 1)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#time_field' do
73
+ context 'when it is nil' do
74
+ before { model.send :write_attribute, :started_at_utc, nil }
75
+
76
+ it 'is nil' do
77
+ model.started_at.should be_nil
78
+ end
79
+ end
80
+
81
+ context 'when there is no time zone' do
82
+ let(:raw_time_value) { Time.utc(2012, 1, 1, 12, 0, 0) }
83
+
84
+ before do
85
+ model.send :write_attribute, :started_at_utc, raw_time_value
86
+ model.stub(:time_zone).and_return nil
87
+ end
88
+
89
+ it 'returns the raw time field' do
90
+ model.started_at.should eql raw_time_value
91
+ end
92
+ end
93
+
94
+ context 'when it is something other than a Time' do
95
+ before { model.send :write_attribute, :started_at_utc, 5 }
96
+
97
+ it 'returns the raw value' do
98
+ model.started_at.should eql 5
99
+ end
100
+ end
101
+
102
+ context 'when the time zone is set properly' do
103
+ before { model.stub(:time_zone).and_return 'Alaska' }
104
+
105
+ context 'when it is a time' do
106
+ before { model.send :write_attribute, :started_at_utc, Time.utc(2012, 1, 2, 12, 59, 1) }
107
+
108
+ it 'returns the time in the time zone' do
109
+ model.started_at.should eql alaskan_time_zone.parse('2012-01-02 3:59:01')
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '#time_field=' do
116
+ let(:raw_time_field) { model.started_at_utc }
117
+
118
+ context 'when the time zone is set' do
119
+ before { model.time_zone = alaskan_time_zone.name }
120
+
121
+ context 'and the field is set to nil' do
122
+ before { model.started_at = nil }
123
+
124
+ it 'the time field is nil' do
125
+ raw_time_field.should be_nil
126
+ end
127
+
128
+ it 'does not need to be converted' do
129
+ model.send(:greenwich_time_field_needs_conversion?, 'started_at', 'time_zone').should be_false
130
+ end
131
+ end
132
+
133
+ context 'and the field is set to something which cannot be converted to a time' do
134
+ before { model.started_at = 'foo' }
135
+
136
+ it 'the time field is nil' do
137
+ raw_time_field.should be_nil
138
+ end
139
+
140
+ it 'does not need to be converted' do
141
+ model.send(:greenwich_time_field_needs_conversion?, 'started_at', 'time_zone').should be_false
142
+ end
143
+ end
144
+
145
+ context 'and the field is set with UTC time' do
146
+ before { model.started_at = Time.utc(2012, 1, 2, 12, 59, 1) }
147
+
148
+ it 'the time field is adjusted for the time zone' do
149
+ raw_time_field.should eql Time.utc(2012, 1, 2, 21, 59, 1)
150
+ end
151
+
152
+ it 'does not need to be converted' do
153
+ model.send(:greenwich_time_field_needs_conversion?, 'started_at', 'time_zone').should be_false
154
+ end
155
+ end
156
+ end
157
+
158
+ context 'when the time zone is not set' do
159
+ before { model.time_zone = nil }
160
+
161
+ context 'and the time field is set' do
162
+ before { model.started_at = Time.utc(2012, 1, 2, 12, 59, 1) }
163
+
164
+ it 'the time field is not adjusted' do
165
+ raw_time_field.should eql Time.utc(2012, 1, 2, 12, 59, 1)
166
+ end
167
+
168
+ it 'needs to be converted' do
169
+ model.send(:greenwich_time_field_needs_conversion?, 'started_at', 'time_zone').should be_true
170
+ end
171
+ end
172
+
173
+ context 'and the time field is not set' do
174
+ before { model.started_at = nil }
175
+
176
+ it 'the time field is nil' do
177
+ raw_time_field.should be_nil
178
+ end
179
+
180
+ it 'does not need to be converted' do
181
+ model.send(:greenwich_time_field_needs_conversion?, 'started_at', 'time_zone').should be_false
182
+ end
183
+ end
184
+ end
185
+ end
186
+
187
+ context 'when it is saved to the database and reloaded' do
188
+ before do
189
+ model.started_at_utc = Time.utc(2012, 1, 2, 21, 59, 1)
190
+ model.time_zone = 'Alaska'
191
+ model.save!
192
+
193
+ model.reload
194
+ end
195
+
196
+ context 'and the time zone is set' do
197
+ before { model.time_zone = 'Hawaii' }
198
+
199
+ it 'does not modify the UTC time' do
200
+ model.started_at_utc.should eql Time.utc(2012, 1, 2, 21, 59, 1)
201
+ end
202
+ end
203
+
204
+ it 'converts the time field to the local time' do
205
+ model.started_at.should_not be_utc
206
+ model.started_at.should eql alaskan_time_zone.parse('2012-01-02 12:59:01')
207
+ end
208
+
209
+ it 'converts the time field to a TimeWithZone' do
210
+ model.started_at.should be_a ActiveSupport::TimeWithZone
211
+ end
212
+ end
213
+ end
214
+
215
+ describe '.time_zone' do
216
+ let(:model) { ModelWithTimeZone.new }
217
+ let(:alaskan_time_zone) { ActiveSupport::TimeZone.new('Alaska') }
218
+
219
+ context '#time_zone' do
220
+ context 'when the object does have a time zone' do
221
+ before { model.send(:write_attribute, :time_zone, alaskan_time_zone.name) }
222
+
223
+ it 'is the time zone' do
224
+ model.time_zone.should eql alaskan_time_zone
225
+ end
226
+ end
227
+
228
+ context 'when the object does not have a time zone' do
229
+ before { model.send(:write_attribute, :time_zone, nil) }
230
+
231
+ it 'is nil' do
232
+ model.time_zone.should be_nil
233
+ end
234
+ end
235
+ end
236
+
237
+ describe '#time_zone=' do
238
+ let(:model) { ModelWithTimeZone.new }
239
+ let(:alaskan_time_zone) { ActiveSupport::TimeZone.new('Alaska') }
240
+ let(:hawaii_time_zone) { ActiveSupport::TimeZone.new('Hawaii') }
241
+ let(:raw_time_field) { model.started_at_utc }
242
+ let(:raw_time_zone) { model.read_attribute(:time_zone) }
243
+
244
+ context 'when it is set after the time field is set' do
245
+ before do
246
+ model.send :write_attribute, :started_at_utc, Time.utc(2012, 1, 2, 12, 59, 1)
247
+ model.time_zone = alaskan_time_zone
248
+ end
249
+
250
+ it 'triggers the time field to be converted' do
251
+ raw_time_field.should eql Time.utc(2012, 1, 2, 21, 59, 1)
252
+ end
253
+
254
+ context 'but when it is set subsequently' do
255
+ before do
256
+ model.time_zone.should_not be_nil
257
+ model.started_at_utc.should_not be_nil
258
+ model.time_zone = hawaii_time_zone
259
+ end
260
+
261
+ it 'does not convert the time field' do
262
+ raw_time_field.should eql Time.utc(2012, 1, 2, 21, 59, 1)
263
+ end
264
+
265
+ context 'if some other time field is then set' do
266
+ before do
267
+ model.send :write_attribute, :ended_at_utc, Time.utc(2012, 1, 2, 13, 59, 1)
268
+ model.time_zone = alaskan_time_zone
269
+ end
270
+
271
+ it 'converts only the time fields that have not already been converted' do
272
+ raw_time_field.should eql Time.utc(2012, 1, 2, 21, 59, 1)
273
+ model.ended_at_utc.should eql Time.utc(2012, 1, 2, 22, 59, 1)
274
+ end
275
+ end
276
+ end
277
+ end
278
+
279
+ context 'when it is set before the time field is set' do
280
+ before { model.time_zone = alaskan_time_zone }
281
+
282
+ it 'sets the time zone but does not touch the time' do
283
+ raw_time_field.should be_nil
284
+ raw_time_zone.should eql 'Alaska'
285
+ end
286
+ end
287
+
288
+ context 'when it is set to an ActiveSupport::TimeZone' do
289
+ before { model.time_zone = alaskan_time_zone }
290
+
291
+ it 'is set properly' do
292
+ raw_time_zone.should eql 'Alaska'
293
+ end
294
+ end
295
+
296
+ context 'when it is set to a time zone name' do
297
+ before { model.time_zone = 'Alaska' }
298
+
299
+ it 'is set properly' do
300
+ raw_time_zone.should eql 'Alaska'
301
+ end
302
+ end
303
+
304
+ context 'when it is set to an invalid time zone' do
305
+ before { model.time_zone = 'I am not a time zone' }
306
+
307
+ it 'is nil' do
308
+ raw_time_zone.should be_nil
309
+ end
310
+ end
311
+ end
312
+ end
313
+ end