tztime 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY ADDED
@@ -0,0 +1,4 @@
1
+ == 0.1.0 2008-04-10
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Jeremy Larkin
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 ADDED
@@ -0,0 +1,135 @@
1
+ = TZTime[http://tztime.rubyforge.org]
2
+
3
+ This library provides time zone localization and conversion with a
4
+ Time-compatible class. The time zone information is provided by the tzinfo gem.
5
+
6
+ While this library is not designed exclusively for Rails, it can be used to
7
+ make time zone aware applications in Rails. See the usage examples below to
8
+ see how you might use this in a Rails project.
9
+
10
+ === Requirements
11
+
12
+ * tztime[http://tzinfo.rubyforge.org]
13
+
14
+
15
+ === Install
16
+
17
+ * sudo gem install tztime
18
+
19
+
20
+ === Usage
21
+
22
+ This demonstrates some common uses of the library. Most of these examples
23
+ demonstrate the use of the Builder class. The Builder creates instances of
24
+ LocalTime. These can be used instead of Time instances, and they therefore have
25
+ the capabilities of the Time class. They also have a few additional methods
26
+ which may be useful. See TZTime::LocalTime for more information.
27
+
28
+ # load the tztime and tzinfo libraries
29
+ require 'tztime'
30
+
31
+ # Create a local time builder to generate and convert localized time objects
32
+ builder = TZTime::LocalTime::Builder.new('America/Los_Angeles')
33
+
34
+ # get the current date
35
+ builder.today # => 2008-04-10 00:00:00 PDT
36
+
37
+ # get the current date and time
38
+ builder.now # => 2008-04-10 15:54:52 PDT
39
+
40
+ # create a specific time value
41
+ time = builder.local(2008, 4, 10, 11, 30)
42
+ p time # => 2008-04-10 11:30:00 PDT
43
+
44
+ # convert the time into utc Time instance
45
+ time = builder.utc(2008, 4, 10, 10, 30)
46
+ p time # => 2008-04-10 07:30:00 PDT
47
+ p time.getutc # => Thu Apr 10 11:30:00 UTC 2008
48
+
49
+ # use a Time instance to create a LocalTime instance (not a conversion)
50
+ time = Time.now # => Thu Apr 10 18:55:21 -0400 2008
51
+ p builder.at(time) # => 2008-04-10 18:55:21 PDT
52
+
53
+ # use a Time instance to create a LocalTime instance converted from the time
54
+ # zone of the Time instance
55
+ time = Time.now # => Thu Apr 10 18:56:16 -0400 2008
56
+ p builder.convert(time) # => 2008-04-10 15:56:16 PDT
57
+
58
+ # convert it using a specific time zone
59
+ p builder.convert(time, 'America/Chicago') # => 2008-04-10 16:56:16 PDT
60
+
61
+ For more information about the Builder class, see TZTime::LocalTime::Builder.
62
+
63
+
64
+ === Usage in ActiveRecord
65
+
66
+ Assuming a +users+ table with this information as a minimum:
67
+
68
+ class CreateUsers < ActiveRecordMigration
69
+ def self.up
70
+ create_table :users do |t|
71
+ t.string :time_zone
72
+ t.timestamps
73
+ end
74
+ end
75
+ end
76
+
77
+
78
+ You need to require the 'tztime/active_record' library. This can be done in the
79
+ environment file or in the model that needs the time zone capabilities. Here,
80
+ we will require it in the model. Note that 'tztime' does not need to be required
81
+ seperately; 'tztime/active_record' will handle requiring it.
82
+
83
+ The User model:
84
+
85
+ require 'tztime/activerecord'
86
+
87
+ class User < ActiveRecord::Base
88
+ acts_as_time_zone
89
+ end
90
+
91
+
92
+ Create an instance and get the current date and time
93
+
94
+ user = User.create :time_zone => 'Eastern Time (US & Canada)'
95
+ user.time_zone_builder.now
96
+ user.created_at # => time in UTC
97
+ user.local_created_at # => time in EDT or EST
98
+
99
+
100
+ Use an instance to convert some other time:
101
+
102
+ entry = Entry.find(...)
103
+ user.time_zone_builder.convert(entry.created_at)
104
+ # because all times in ActiveRecord will now be in UTC, this works too
105
+ user.time_zone_builder.at_utc(entry.created_at)
106
+
107
+ === Todo
108
+
109
+ * Hook into DataMapper and Sequel ORM libraries
110
+
111
+
112
+ === License
113
+
114
+ (The MIT License)
115
+
116
+ Copyright (c) 2008 Jeremy Larkin
117
+
118
+ Permission is hereby granted, free of charge, to any person obtaining
119
+ a copy of this software and associated documentation files (the
120
+ 'Software'), to deal in the Software without restriction, including
121
+ without limitation the rights to use, copy, modify, merge, publish,
122
+ distribute, sublicense, and/or sell copies of the Software, and to
123
+ permit persons to whom the Software is furnished to do so, subject to
124
+ the following conditions:
125
+
126
+ The above copyright notice and this permission notice shall be
127
+ included in all copies or substantial portions of the Software.
128
+
129
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
130
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
131
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
132
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
133
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
134
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
135
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ module TZTime # :nodoc:
2
+ require 'tztime/local_time'
3
+ require 'tztime/local_time/builder'
4
+ require 'tztime/time_zone_element'
5
+ end
@@ -0,0 +1,14 @@
1
+ require 'tztime'
2
+
3
+ ENV['TZ'] ||= 'UTC'
4
+ require 'activerecord' unless defined? ActiveRecord
5
+
6
+ # Adds the capability to store and use time zones in ActiveRecord models.
7
+ #
8
+ # See TZTime::ActiveRecord::Acts::LocalTime::ClassMethods
9
+ module TZTime::ActiveRecord
10
+ require 'tztime/activerecord/acts/local_time'
11
+ end
12
+
13
+ ActiveRecord::Base.send :include, TZTime::ActiveRecord::Acts::LocalTime
14
+ ActiveRecord::Base.default_timezone = :utc
@@ -0,0 +1,110 @@
1
+ module TZTime::ActiveRecord::Acts # :nodoc:
2
+ module LocalTime # :nodoc:
3
+
4
+ def self.included(into)
5
+ into.extend ClassMethods
6
+ end
7
+
8
+ # This acts provides the capabilities for storing time zones and using them
9
+ # to generate and convert times. This requires that ActiveRecord be
10
+ # configured to store times in utc. Requiring tztime/activerecord will
11
+ # configure ActiveRecord itself.
12
+ #
13
+ # This will add a composed_of property using the name provided by the
14
+ # <tt>:time_builder_accessor</tt> (defaults to <tt>:local_time_builder</tt>)
15
+ # and gets the time zone name from the <tt>:time_zone_field</tt> option
16
+ # (defaults to <tt>:time_zone</tt>).
17
+ #
18
+ # All methods that return a Time or DateTime object gain the ability to be
19
+ # localized to the timezone used by the model instance. For example, a
20
+ # <tt>created_at</tt> field value can be localized via <tt>local_created_at</tt>.
21
+ # This is not limited to field accessors; custom methods also gain this
22
+ # capability. For example:
23
+ # class Foo < ActiveRecord::Base
24
+ # acts_as_time_zone
25
+ #
26
+ # def bar
27
+ # Time.now # will be in UTC
28
+ # end
29
+ # end
30
+ #
31
+ # A localized value of <tt>bar</tt> can be accessed via <tt>local_bar</tt>.
32
+ # This value will be converted into a TZTime::LocalTime instance with the
33
+ # time zone set in the Foo instance.
34
+ #
35
+ # ==== Parameters
36
+ # options<Hash>:: See below.
37
+ #
38
+ # ==== Options
39
+ # :time_zone_field<Symbol,String>::
40
+ # The field in the database that holds the time zone name.
41
+ # Default <tt>:time_zone</tt>
42
+ #
43
+ # :time_builder_accessor<Symbol,String>::
44
+ # The name of the +composed_of+ field to create to access the local time
45
+ # builder instance.
46
+ # Default <tt>:local_time_builder</tt>
47
+ #
48
+ # === Usage
49
+ # Create a migration that includes a +time_zone+ field :
50
+ # class CreateSettings < ActiveRecordMigration
51
+ # def self.up
52
+ # create_table :settings do |t|
53
+ # t.string :time_zone
54
+ # t.timestamps
55
+ # end
56
+ # end
57
+ # end
58
+ #
59
+ # Define the Setting model:
60
+ # require 'tztime/activerecord'
61
+ #
62
+ # class Setting < ActiveRecord::Base
63
+ # acts_as_time_zone
64
+ # end
65
+ #
66
+ # Create an instance and get the current date and time
67
+ # setting = Setting.create :time_zone => 'Eastern Time (US & Canada)'
68
+ # setting.time_zone_builder.now
69
+ # setting.created_at # => time in UTC
70
+ # setting.local_created_at # => time in EDT or EST
71
+ module ClassMethods
72
+ def acts_as_local_time(options={})
73
+ options = {
74
+ :time_zone_field => :time_zone,
75
+ :time_builder_accessor => :local_time_builder
76
+ }.merge(options)
77
+
78
+ write_inheritable_attribute(:acts_as_local_time_options, options)
79
+ class_inheritable_reader :acts_as_local_time_options
80
+
81
+ if options[:time_builder_accessor] && options[:time_zone_field]
82
+ composed_of(options[:time_builder_accessor].to_sym, {
83
+ :class_name => 'TZTime::LocalTime::Builder',
84
+ :mapping => %W{#{options[:time_zone_field]} time_zone_name}
85
+ })
86
+ end
87
+
88
+ include InstanceMethods
89
+ end
90
+ end
91
+
92
+ module InstanceMethods # :nodoc:
93
+ def self.included(into)
94
+ into.alias_method_chain :method_missing, :local_time
95
+ end
96
+
97
+ def method_missing_with_local_time(name, *args, &block)
98
+ ns = name.to_s
99
+ if ns =~ /local_(.+)/ &&
100
+ value = send!($1, *args, &block)
101
+ if value.is_a?(Time) || value.is_a?(DateTime)
102
+ builder = send!(acts_as_local_time_options[:time_builder_accessor])
103
+ return builder.at_utc(value)
104
+ end
105
+ end
106
+ method_missing_without_local_time(name, *args, &block)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,313 @@
1
+ require 'time'
2
+ require 'rubygems'
3
+ require 'tzinfo'
4
+
5
+ # A LocalTime instance wraps a Time value and a TZInfo time zone definition.
6
+ # The LocalTime class acts as a proxy to the Time value, enabling instances
7
+ # of this class to walk and talk like the Time duck.
8
+ #
9
+ # Certain methods are implemented directly in order to behave as expected
10
+ # +strftime+, +httpdate+, +rfc2822+, and +xmlschema+ are implemented to take
11
+ # proper conversions and/or time zone abbreviations into account. +getutc+
12
+ # has been implemented to create a time value converted to UTC and returned.
13
+ # (instead of returning a LocalTime instance). +to_time+, +to_date+, and
14
+ # +to_datetime+ will convert the time and return Time, Date, and DateTime
15
+ # values, respectively, converted into Universal Time. The behavior of
16
+ # +to_date+ and +to_datetime+ can be modified to not convert to UTC.
17
+ class TZTime::LocalTime
18
+ include Comparable
19
+
20
+ # The Time value wrapped by this instance.
21
+ attr_reader :time
22
+
23
+ # The TZInfo time zone definition that represents the time zone of the value
24
+ attr_reader :time_zone
25
+
26
+ # Creates a new LocalTime instance that wraps the value of +time+. +time+
27
+ # must be an instance of Time, and +time_zone must be an instance of
28
+ # TZInfo::Timezone. In most circumstances, these should not be created
29
+ # directly. Typically they will be created by a TZTime::LocalTime::Builder
30
+ # instance.
31
+ #
32
+ # ==== Parameters
33
+ # time<Time>::
34
+ # The date and time in the desired time zone. The time zone of the instance
35
+ # is ignored.
36
+ # time_zone<TZInfo::Timezone>::
37
+ # The time zone of the instance.
38
+ def initialize(time, time_zone)
39
+ raise ArgumentError, "The 'time' parameter must be an instance of Time" unless time.is_a?(Time)
40
+ raise ArgumentError, "The 'time_zone' parameter must be an instance of TZInfo::Timezone" unless time_zone.is_a?(TZInfo::Timezone)
41
+ @time = time
42
+ @time_zone = time_zone
43
+ end
44
+
45
+ # call-seq:
46
+ # time + numeric => time
47
+ #
48
+ # Addition. Adds some number of seconds (possibly fractional) to time and
49
+ # returns that value as a new time.
50
+ #
51
+ # builder = TZTime::LocalTime::Builder.new('America/New_York')
52
+ # t = builder.local(2007, 12, 16, 10, 30) # => 2007-12-16 10:30:00 EST
53
+ # t + (60 * 60 * 24) # => 2007-12-17 10:30:00 EST
54
+ def +(value)
55
+ self.class.new(@time + (value.is_a?(self.class) ? value.time : value), @time_zone)
56
+ end
57
+
58
+ # call-seq:
59
+ # time - other_time => float
60
+ # time - numeric => time
61
+ #
62
+ # Difference. Returns a new time that represents the difference between two
63
+ # times, or subtracts the given number of seconds in numeric from time.
64
+ #
65
+ # builder = TZTime::LocalTime::Builder.new('America/New_York')
66
+ # t = builder.local(2007, 12, 16, 10, 30) # => 2007-12-16 10:30:00 EST
67
+ # t2 = builder.local(2007, 12, 17, 10, 30) # => 2007-12-17 10:30:00 EST
68
+ # t2 - (60 * 60 * 24) # => 2007-12-16 10:30:00 EST
69
+ # t2 - t # => 86400
70
+ def -(value)
71
+ t = @time - (value.is_a?(self.class) ? value.time : value)
72
+ t.is_a?(Numeric) ? t : self.class.new(t, @time_zone)
73
+ end
74
+
75
+ # The full name of the time zone. This is the name used by TZInfo time zone definition
76
+ def time_zone_name
77
+ time_zone.name
78
+ end
79
+
80
+ # The +time_zone_abbreviation+ as a string
81
+ def zone
82
+ time_zone_abbreviation.to_s
83
+ end
84
+
85
+ # The offset from Universal Time in seconds
86
+ def time_zone_offset
87
+ time_zone_period.utc_total_offset
88
+ end
89
+
90
+ alias utc_offset time_zone_offset
91
+ alias gm_offset time_zone_offset
92
+
93
+ # The time zone offset as a fraction of a day (as a Rational).
94
+ def time_zone_offset_fraction
95
+ Rational(time_zone_offset, 86_400)
96
+ end
97
+
98
+ alias offset_fraction time_zone_offset_fraction
99
+
100
+ # Get the abbreviated time zone name as a Symbol. (ex :EDT, :UTC)
101
+ def time_zone_abbreviation
102
+ time_zone_period.abbreviation
103
+ end
104
+
105
+ alias time_zone_identifier time_zone_abbreviation
106
+
107
+ # Get a Time instance converted to UTC from the local time.
108
+ def getutc
109
+ @getutc ||= time_zone_period.to_utc(@time)
110
+ end
111
+
112
+ alias utc getutc
113
+ alias getgm getutc
114
+ alias to_time getutc
115
+
116
+ def getlocal
117
+ dup
118
+ end
119
+
120
+ # Convert this to a Date instance in the Universal Time. If +utc+ is
121
+ # +false+, then the value will not be converted to Universal Time first.
122
+ # Note, this can create a misleading value because Date instance cannot
123
+ # store a time zone offset.
124
+ def to_date(utc=true)
125
+ t = utc ? getutc : @time
126
+ Date.civil(t.year, t.month, t.day)
127
+ end
128
+
129
+ # Convert this to a DateTime instance in the Univeral Time. If +utc+ is
130
+ # +false+, then a DateTime with the proper time zone offset will be created.
131
+ def to_datetime(utc=true)
132
+ t = utc ? getutc : @time
133
+ DateTime.civil(t.year, t.month, t.day, t.hour, t.min, t.sec, utc ? 0 : time_zone_offset_fraction)
134
+ end
135
+
136
+ # Returns the +hour+, +min+, and +sec+ as seconds. The seconds are offset by
137
+ # the +time_zone_offset+, which can adjust the value below 0 or above 86400
138
+ # (one day).
139
+ def utc_day_seconds
140
+ local_day_seconds - time_zone_offset
141
+ end
142
+
143
+ alias gm_day_seconds gm_day_seconds
144
+
145
+ # Returns the +hour+, +min+, and +sec+ as seconds.
146
+ def local_day_seconds
147
+ @time.sec + (@time.min * 60) + (@time.hour * 3600)
148
+ end
149
+
150
+ alias day_seconds local_day_seconds
151
+
152
+ # Compare this instance's value of +time+ with another LocalTime or Time value.
153
+ def <=>(value)
154
+ getutc <=> value.getutc
155
+ end
156
+
157
+ # Determine if the time zone is in Universal Time.
158
+ def utc?
159
+ time_zone_period.abbreviation == :UTC
160
+ end
161
+
162
+ # Find the <tt>TZInfo::TimezonePeriod<?tt> for the +time_zone+
163
+ def time_zone_period
164
+ return @time_zone_period if defined?(@time_zone_period)
165
+ @time_zone_period = @time_zone.period_for_local(@time, @time.dst?)
166
+ end
167
+
168
+ # Determine if the current time is during Daylight Savings Time.
169
+ def dst?
170
+ time_zone_period.dst?
171
+ end
172
+
173
+ # Formats the time according to the directives in the given format string.
174
+ # Any text not listed as a directive will be passed through to the output string.
175
+ #
176
+ # Format meaning:
177
+ #
178
+ # %a - The abbreviated weekday name ('Sun')
179
+ # %A - The full weekday name ('Sunday')
180
+ # %b - The abbreviated month name ('Jan')
181
+ # %B - The full month name ('January')
182
+ # %c - The preferred local date and time representation
183
+ # %d - Day of the month (01..31)
184
+ # %H - Hour of the day, 24-hour clock (00..23)
185
+ # %I - Hour of the day, 12-hour clock (01..12)
186
+ # %j - Day of the year (001..366)
187
+ # %m - Month of the year (01..12)
188
+ # %M - Minute of the hour (00..59)
189
+ # %p - Meridian indicator ('AM' or 'PM')
190
+ # %P - Meridian indicator ('a' or 'p')
191
+ # %S - Second of the minute (00..60)
192
+ # %U - Week number of the current year,
193
+ # starting with the first Sunday as the first
194
+ # day of the first week (00..53)
195
+ # %W - Week number of the current year,
196
+ # starting with the first Monday as the first
197
+ # day of the first week (00..53)
198
+ # %w - Day of the week (Sunday is 0, 0..6)
199
+ # %x - Preferred representation for the date alone, no time
200
+ # %X - Preferred representation for the time alone, no date
201
+ # %y - Year without a century (00..99)
202
+ # %Y - Year with century
203
+ # %Z - Time zone name
204
+ # %% - Literal '%' character
205
+ #
206
+ # t = Time.now
207
+ # t.strftime("Printed on %m/%d/%Y") #=> "Printed on 04/09/2003"
208
+ # t.strftime("at %I:%M%p") #=> "at 08:56AM"
209
+ def strftime(string)
210
+ @time.strftime(string.
211
+ gsub(/([^%]|\A)%Z/, "\\1#{zone}").
212
+ gsub(/([^%]|\A)%P/, "\\1#{@time.hour >= 12 ? 'p' : 'a'}"))
213
+ end
214
+
215
+ # Returns a string which represents the time as rfc1123-date of HTTP-date
216
+ # defined by RFC 2616:
217
+ # day-of-week, DD month-name CCYY hh:mm:ss GMT
218
+ #
219
+ # Note that the result is always UTC (GMT).
220
+ def httpdate
221
+ getutc.httpdate
222
+ end
223
+
224
+ alias rfc1123 httpdate
225
+
226
+ # Returns a string which represents the time as date-time defined by RFC 2822:
227
+ # day-of-week, DD month-name CCYY hh:mm:ss zone
228
+ # where zone is [+-]hhmm.
229
+ #
230
+ # If +self+ is a UTC time, -0000 is used as zone.
231
+ def rfc2822
232
+ sprintf('%s, %02d %s %d %02d:%02d:%02d ',
233
+ Time::RFC2822_DAY_NAME[@time.wday],
234
+ @time.day, Time::RFC2822_MONTH_NAME[@time.mon-1], @time.year,
235
+ @time.hour, @time.min, @time.sec) +
236
+ if utc?
237
+ '-0000'
238
+ else
239
+ off = utc_offset
240
+ sign = off < 0 ? '-' : '+'
241
+ sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60))
242
+ end
243
+ end
244
+
245
+ alias rfc822 rfc2822
246
+
247
+ # Returns a string which represents the time as dateTime defined by XML Schema:
248
+ # CCYY-MM-DDThh:mm:ssTZD
249
+ # CCYY-MM-DDThh:mm:ss.sssTZD
250
+ # where TZD is Z or [+-]hh:mm.
251
+ #
252
+ # If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
253
+ #
254
+ # +fraction_digits+ specifies a number of digits of fractional seconds. Its
255
+ # default value is 0.
256
+ def xmlschema(fraction_digits=0)
257
+ sprintf('%d-%02d-%02dT%02d:%02d:%02d',
258
+ @time.year, @time.mon, @time.day, @time.hour, @time.min, @time.sec) +
259
+ if fraction_digits.nil? || fraction_digits == 0
260
+ ''
261
+ elsif fraction_digits <= 6
262
+ '.' + sprintf('%06d', @time.usec)[0, fraction_digits]
263
+ else
264
+ '.' + sprintf('%06d', @time.usec) + '0' * (fraction_digits - 6)
265
+ end +
266
+ if utc?
267
+ 'Z'
268
+ else
269
+ off = utc_offset
270
+ sign = off < 0 ? '-' : '+'
271
+ sprintf('%s%02d:%02d', sign, *(off.abs / 60).divmod(60))
272
+ end
273
+ end
274
+
275
+ alias iso8601 xmlschema
276
+
277
+ # Converts the time into an xml-compatible string. This is the same results
278
+ # as using xmlschema, except that it can accept options. There are no options
279
+ # for the method, it is accepted for campatibility with Rails.
280
+ def to_xml(options=nil)
281
+ xmlschema
282
+ end
283
+
284
+ def to_s #:nodoc:
285
+ strftime("%Y-%m-%d %H:%M:%S %Z")
286
+ end
287
+
288
+ alias inspect to_s # :nodoc:
289
+
290
+ def dup # :nodoc:
291
+ self.class.new(@time.dup, @time_zone)
292
+ end
293
+
294
+ alias clone dup # :nodoc:
295
+
296
+ # Also check if +@time+ can respond to a method because LocalTime acts as a
297
+ # proxy to the underlying Time instance.
298
+ def respond_to?(name) # :nodoc:
299
+ super || @time.respond_to?(name)
300
+ end
301
+
302
+ # Pass on call to +@time+ unless it does not respond to the requested
303
+ # method. If +@time+ does respond and the value returned is a new Time
304
+ # value, that new value will be wrapped in a new LocalTime instance.
305
+ def method_missing(name, *args, &block) #:nodoc:
306
+ if @time.respond_to?(name)
307
+ val = @time.send(name, *args, &block)
308
+ val.is_a?(Time) ? self.class.new(val, @time_zone) : val
309
+ else
310
+ super
311
+ end
312
+ end
313
+ end