tztime 0.1.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/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
|