tztime 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +4 -0
- data/LICENSE +20 -0
- data/README +135 -0
- data/lib/tztime.rb +5 -0
- data/lib/tztime/activerecord.rb +14 -0
- data/lib/tztime/activerecord/acts/local_time.rb +110 -0
- data/lib/tztime/local_time.rb +313 -0
- data/lib/tztime/local_time/builder.rb +424 -0
- data/lib/tztime/time_zone_element.rb +81 -0
- data/test/test_active_record.rb +64 -0
- data/test/test_active_support.rb +14 -0
- data/test/test_format.rb +18 -0
- data/test/test_helper.rb +2 -0
- data/test/test_time_zone.rb +77 -0
- metadata +85 -0
data/HISTORY
ADDED
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.
|
data/lib/tztime.rb
ADDED
@@ -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
|