summaryrefslogtreecommitdiff
path: root/lib/time.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/time.rb')
-rw-r--r--lib/time.rb478
1 files changed, 288 insertions, 190 deletions
diff --git a/lib/time.rb b/lib/time.rb
index 12c2b30e25..e6aab3fa5d 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -1,5 +1,10 @@
+# frozen_string_literal: true
+# shareable_constant_value: literal
+
require 'date'
+# :stopdoc:
+
# = time.rb
#
# When 'time' is required, Time is extended with additional methods for parsing
@@ -16,75 +21,14 @@ require 'date'
# 8601}[http://www.iso.org/iso/date_and_time_format])
# * various formats handled by Date._parse
# * custom formats handled by Date._strptime
-#
-# == Examples
-#
-# All examples assume you have loaded Time with:
-#
-# require 'time'
-#
-# All of these examples were done using the EST timezone which is GMT-5.
-#
-# === Converting to a String
-#
-# t = Time.now
-# t.iso8601 # => "2011-10-05T22:26:12-04:00"
-# t.rfc2822 # => "Wed, 05 Oct 2011 22:26:12 -0400"
-# t.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT"
-#
-# === Time.parse
-#
-# #parse takes a string representation of a Time and attempts to parse it
-# using a heuristic.
-#
-# Date.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500
-#
-# Any missing pieces of the date are inferred based on the current date.
-#
-# # assuming the current date is "2011-10-31"
-# Time.parse("12:00") #=> 2011-10-31 12:00:00 -0500
-#
-# We can change the date used to infer our missing elements by passing a second
-# object that responds to #mon, #day and #year, such as Date, Time or DateTime.
-# We can also use our own object.
-#
-# class MyDate
-# attr_reader :mon, :day, :year
-#
-# def initialize(mon, day, year)
-# @mon, @day, @year = mon, day, year
-# end
-# end
-#
-# d = Date.parse("2010-10-28")
-# t = Time.parse("2010-10-29")
-# dt = DateTime.parse("2010-10-30")
-# md = MyDate.new(10,31,2010)
-#
-# Time.parse("12:00", d) #=> 2010-10-28 12:00:00 -0500
-# Time.parse("12:00", t) #=> 2010-10-29 12:00:00 -0500
-# Time.parse("12:00", dt) #=> 2010-10-30 12:00:00 -0500
-# Time.parse("12:00", md) #=> 2010-10-31 12:00:00 -0500
-#
-# #parse also accepts an optional block. You can use this block to specify how
-# to handle the year component of the date. This is specifically designed for
-# handling two digit years. For example, if you wanted to treat all two digit
-# years prior to 70 as the year 2000+ you could write this:
-#
-# Time.parse("01-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
-# #=> 2001-10-31 00:00:00 -0500
-# Time.parse("70-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
-# #=> 1970-10-31 00:00:00 -0500
-#
-# === Time.strptime
-#
-# #strptime works similar to +parse+ except that instead of using a heuristic
-# to detect the format of the input string, you provide a second argument that
-# is describes the format of the string. For example:
-#
-# Time.strptime("2000-10-31", "%Y-%m-%d") #=> 2000-10-31 00:00:00 -0500
+# :startdoc:
+
+# #
class Time
+
+ VERSION = "0.4.2" # :nodoc:
+
class << Time
#
@@ -129,23 +73,34 @@ class Time
#
# If +zone_offset+ is unable to determine the offset, nil will be
# returned.
- def zone_offset(zone, year=self.now.year)
+ #
+ # require 'time'
+ #
+ # Time.zone_offset("EST") #=> -18000
+ #
+ # You must require 'time' to use this method.
+ #
+ def zone_offset(zone, year=nil)
off = nil
zone = zone.upcase
- if /\A([+-])(\d\d):?(\d\d)\z/ =~ zone
- off = ($1 == '-' ? -1 : 1) * ($2.to_i * 60 + $3.to_i) * 60
- elsif /\A[+-]\d\d\z/ =~ zone
+ if /\A([+-])(\d\d)(:?)(\d\d)(?:\3(\d\d))?\z/ =~ zone
+ off = ($1 == '-' ? -1 : 1) * (($2.to_i * 60 + $4.to_i) * 60 + $5.to_i)
+ elsif zone.match?(/\A[+-]\d\d\z/)
off = zone.to_i * 3600
elsif ZoneOffset.include?(zone)
off = ZoneOffset[zone] * 3600
- elsif ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false)
- off = t.utc_offset
- elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false)
- off = t.utc_offset
+ else
+ year ||= self.now.year
+ if ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false)
+ off = t.utc_offset
+ elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false)
+ off = t.utc_offset
+ end
end
off
end
+ # :stopdoc:
def zone_utc?(zone)
# * +0000
# In RFC 2822, +0000 indicate a time zone at Universal Time.
@@ -166,16 +121,30 @@ class Time
# They are not appropriate for specific time zone such as
# Europe/London because time zone neutral,
# So -00:00 and -0000 are treated as UTC.
- if /\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i =~ zone
- true
+ zone.match?(/\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i)
+ end
+ private :zone_utc?
+
+ def force_zone!(t, zone, offset=nil)
+ if zone_utc?(zone)
+ t.utc
+ elsif offset ||= zone_offset(zone)
+ # Prefer the local timezone over the fixed offset timezone because
+ # the former is a real timezone and latter is an artificial timezone.
+ t.localtime
+ if t.utc_offset != offset
+ # Use the fixed offset timezone only if the local timezone cannot
+ # represent the given offset.
+ t.localtime(offset)
+ end
else
- false
+ t.localtime
end
end
- private :zone_utc?
+ private :force_zone!
- LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
- CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+ LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc:
+ CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # :nodoc:
def month_days(y, m)
if ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)
LeapYearMonthDays[m-1]
@@ -196,7 +165,8 @@ class Time
if o != 0 then hour += o; o, hour = hour.divmod(24); off += o end
if off != 0
day += off
- if month_days(year, mon) < day
+ days = month_days(year, mon)
+ if days and days < day
mon += 1
if 12 < mon
mon = 1
@@ -228,9 +198,48 @@ class Time
end
private :apply_offset
- def make_time(year, mon, day, hour, min, sec, sec_fraction, zone, now)
+ def make_time(date, year, yday, mon, day, hour, min, sec, sec_fraction, zone, now)
+ if !year && !yday && !mon && !day && !hour && !min && !sec && !sec_fraction
+ raise ArgumentError, "no time information in #{date.inspect}"
+ end
+
+ off = nil
+ if year || now
+ off_year = year || now.year
+ off = zone_offset(zone, off_year) if zone
+ end
+
+ if yday
+ unless (1..366) === yday
+ raise ArgumentError, "yday #{yday} out of range"
+ end
+ mon, day = (yday-1).divmod(31)
+ mon += 1
+ day += 1
+ t = make_time(date, year, nil, mon, day, hour, min, sec, sec_fraction, zone, now)
+ diff = yday - t.yday
+ return t if diff.zero?
+ day += diff
+ if day > 28 and day > (mday = month_days(off_year, mon))
+ if (mon += 1) > 12
+ raise ArgumentError, "yday #{yday} out of range"
+ end
+ day -= mday
+ end
+ return make_time(date, year, nil, mon, day, hour, min, sec, sec_fraction, zone, now)
+ end
+
+ if now and now.respond_to?(:getlocal)
+ if off
+ now = now.getlocal(off) if now.utc_offset != off
+ else
+ now = now.getlocal
+ end
+ end
+
usec = nil
usec = sec_fraction * 1000000 if sec_fraction
+
if now
begin
break if year; year = now.year
@@ -251,40 +260,93 @@ class Time
sec ||= 0
usec ||= 0
- off = nil
- off = zone_offset(zone, year) if zone
+ if year != off_year
+ off = nil
+ off = zone_offset(zone, year) if zone
+ end
if off
year, mon, day, hour, min, sec =
apply_offset(year, mon, day, hour, min, sec, off)
t = self.utc(year, mon, day, hour, min, sec, usec)
- t.localtime if !zone_utc?(zone)
+ force_zone!(t, zone, off)
t
else
self.local(year, mon, day, hour, min, sec, usec)
end
end
private :make_time
+ # :startdoc:
#
- # Parses +date+ using Date._parse and converts it to a Time object.
+ # Takes a string representation of a Time and attempts to parse it
+ # using a heuristic.
#
- # If a block is given, the year described in +date+ is converted by the
- # block. For example:
+ # This method **does not** function as a validator. If the input
+ # string does not match valid formats strictly, you may get a
+ # cryptic result. Should consider to use Time.strptime instead
+ # of this method as possible.
+ #
+ # require 'time'
+ #
+ # Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500
#
- # Time.parse(...) {|y| 0 <= y && y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
+ # Any missing pieces of the date are inferred based on the current date.
+ #
+ # require 'time'
+ #
+ # # assuming the current date is "2011-10-31"
+ # Time.parse("12:00") #=> 2011-10-31 12:00:00 -0500
+ #
+ # We can change the date used to infer our missing elements by passing a second
+ # object that responds to #mon, #day and #year, such as Date, Time or DateTime.
+ # We can also use our own object.
+ #
+ # require 'time'
+ #
+ # class MyDate
+ # attr_reader :mon, :day, :year
+ #
+ # def initialize(mon, day, year)
+ # @mon, @day, @year = mon, day, year
+ # end
+ # end
+ #
+ # d = Date.parse("2010-10-28")
+ # t = Time.parse("2010-10-29")
+ # dt = DateTime.parse("2010-10-30")
+ # md = MyDate.new(10,31,2010)
+ #
+ # Time.parse("12:00", d) #=> 2010-10-28 12:00:00 -0500
+ # Time.parse("12:00", t) #=> 2010-10-29 12:00:00 -0500
+ # Time.parse("12:00", dt) #=> 2010-10-30 12:00:00 -0500
+ # Time.parse("12:00", md) #=> 2010-10-31 12:00:00 -0500
+ #
+ # If a block is given, the year described in +date+ is converted
+ # by the block. This is specifically designed for handling two
+ # digit years. For example, if you wanted to treat all two digit
+ # years prior to 70 as the year 2000+ you could write this:
+ #
+ # require 'time'
+ #
+ # Time.parse("01-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
+ # #=> 2001-10-31 00:00:00 -0500
+ # Time.parse("70-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
+ # #=> 1970-10-31 00:00:00 -0500
#
# If the upper components of the given time are broken or missing, they are
# supplied with those of +now+. For the lower components, the minimum
# values (1 or 0) are assumed if broken or missing. For example:
#
- # # Suppose it is "Thu Nov 29 14:33:20 GMT 2001" now and
- # # your time zone is GMT:
- # now = Time.parse("Thu Nov 29 14:33:20 GMT 2001")
- # Time.parse("16:30", now) #=> 2001-11-29 16:30:00 +0900
- # Time.parse("7/23", now) #=> 2001-07-23 00:00:00 +0900
- # Time.parse("Aug 31", now) #=> 2001-08-31 00:00:00 +0900
- # Time.parse("Aug 2000", now) #=> 2000-08-01 00:00:00 +0900
+ # require 'time'
+ #
+ # # Suppose it is "Thu Nov 29 14:33:20 2001" now and
+ # # your time zone is EST which is GMT-5.
+ # now = Time.parse("Thu Nov 29 14:33:20 2001")
+ # Time.parse("16:30", now) #=> 2001-11-29 16:30:00 -0500
+ # Time.parse("7/23", now) #=> 2001-07-23 00:00:00 -0500
+ # Time.parse("Aug 31", now) #=> 2001-08-31 00:00:00 -0500
+ # Time.parse("Aug 2000", now) #=> 2000-08-01 00:00:00 -0500
#
# Since there are numerous conflicts among locally defined time zone
# abbreviations all over the world, this method is not intended to
@@ -323,23 +385,24 @@ class Time
def parse(date, now=self.now)
comp = !block_given?
d = Date._parse(date, comp)
- if !d[:year] && !d[:mon] && !d[:mday] && !d[:hour] && !d[:min] && !d[:sec] && !d[:sec_fraction]
- raise ArgumentError, "no time information in #{date.inspect}"
- end
year = d[:year]
year = yield(year) if year && !comp
- make_time(year, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
+ make_time(date, year, d[:yday], d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
end
#
- # Parses +date+ using Date._strptime and converts it to a Time object.
+ # Works similar to +parse+ except that instead of using a
+ # heuristic to detect the format of the input string, you provide
+ # a second argument that describes the format of the string.
+ #
+ # Raises ArgumentError if the date or format is invalid.
#
# If a block is given, the year described in +date+ is converted by the
# block. For example:
#
# Time.strptime(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
#
- # Below is a list of the formating options:
+ # Below is a list of the formatting options:
#
# %a :: The abbreviated weekday name ("Sun")
# %A :: The full weekday name ("Sunday")
@@ -348,9 +411,12 @@ class Time
# %c :: The preferred local date and time representation
# %C :: Century (20 in 2009)
# %d :: Day of the month (01..31)
- # %D :: Date (%m/%d/%y)
+ # %D :: \Date (%m/%d/%y)
# %e :: Day of the month, blank-padded ( 1..31)
# %F :: Equivalent to %Y-%m-%d (the ISO 8601 date format)
+ # %g :: The last two digits of the commercial year
+ # %G :: The week-based year according to ISO-8601 (week 1 starts on Monday
+ # and includes January 4)
# %h :: Equivalent to %b
# %H :: Hour of the day, 24-hour clock (00..23)
# %I :: Hour of the day, 12-hour clock (01..12)
@@ -361,10 +427,7 @@ class Time
# %m :: Month of the year (01..12)
# %M :: Minute of the hour (00..59)
# %n :: Newline (\n)
- # %N :: Fractional seconds digits, default is 9 digits (nanosecond)
- # %3N :: millisecond (3 digits)
- # %6N :: microsecond (6 digits)
- # %9N :: nanosecond (9 digits)
+ # %N :: Fractional seconds digits
# %p :: Meridian indicator ("AM" or "PM")
# %P :: Meridian indicator ("am" or "pm")
# %r :: time, 12-hour (same as %I:%M:%S %p)
@@ -384,28 +447,49 @@ class Time
# %x :: Preferred representation for the date alone, no time
# %X :: Preferred representation for the time alone, no date
# %y :: Year without a century (00..99)
- # %Y :: Year with century
- # %z :: Time zone as hour offset from UTC (e.g. +0900)
- # %Z :: Time zone name
+ # %Y :: Year which may include century, if provided
+ # %z :: \Time zone as hour offset from UTC (e.g. +0900)
+ # %Z :: \Time zone name
# %% :: Literal "%" character
-
+ # %+ :: date(1) (%a %b %e %H:%M:%S %Z %Y)
+ #
+ # require 'time'
+ #
+ # Time.strptime("2000-10-31", "%Y-%m-%d") #=> 2000-10-31 00:00:00 -0500
+ #
+ # You must require 'time' to use this method.
+ #
def strptime(date, format, now=self.now)
d = Date._strptime(date, format)
- raise ArgumentError, "invalid strptime format - `#{format}'" unless d
+ raise ArgumentError, "invalid date or strptime format - '#{date}' '#{format}'" unless d
if seconds = d[:seconds]
- if offset = d[:offset]
- Time.at(seconds).localtime(offset)
+ if sec_fraction = d[:sec_fraction]
+ usec = sec_fraction * 1000000
+ usec *= -1 if seconds < 0
else
- Time.at(seconds)
+ usec = 0
+ end
+ t = Time.at(seconds, usec)
+ if zone = d[:zone]
+ force_zone!(t, zone)
end
else
year = d[:year]
year = yield(year) if year && block_given?
- make_time(year, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
+ yday = d[:yday]
+ if (d[:cwyear] && !year) || ((d[:cwday] || d[:cweek]) && !(d[:mon] && d[:mday]))
+ # make_time doesn't deal with cwyear/cwday/cweek
+ return Date.strptime(date, format).to_time
+ end
+ if (d[:wnum0] || d[:wnum1]) && !yday && !(d[:mon] && d[:mday])
+ yday = Date.strptime(date, format).yday
+ end
+ t = make_time(date, year, yday, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
end
+ t
end
- MonthValue = {
+ MonthValue = { # :nodoc:
'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6,
'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' =>10, 'NOV' =>11, 'DEC' =>12
}
@@ -420,6 +504,11 @@ class Time
#
# See #rfc2822 for more information on this format.
#
+ # require 'time'
+ #
+ # Time.rfc2822("Wed, 05 Oct 2011 22:26:12 -0400")
+ # #=> 2010-10-05 22:26:12 -0400
+ #
# You must require 'time' to use this method.
#
def rfc2822(date)
@@ -429,32 +518,34 @@ class Time
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+
(\d{2,})\s+
(\d{2})\s*
- :\s*(\d{2})\s*
- (?::\s*(\d{2}))?\s+
+ :\s*(\d{2})
+ (?:\s*:\s*(\d\d))?\s+
([+-]\d{4}|
UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-IK-Z])/ix =~ date
# Since RFC 2822 permit comments, the regexp has no right anchor.
day = $1.to_i
mon = MonthValue[$2.upcase]
year = $3.to_i
+ short_year_p = $3.length <= 3
hour = $4.to_i
min = $5.to_i
sec = $6 ? $6.to_i : 0
zone = $7
- # following year completion is compliant with RFC 2822.
- year = if year < 50
- 2000 + year
- elsif year < 1000
- 1900 + year
- else
- year
- end
+ if short_year_p
+ # following year completion is compliant with RFC 2822.
+ year = if year < 50
+ 2000 + year
+ else
+ 1900 + year
+ end
+ end
+ off = zone_offset(zone)
year, mon, day, hour, min, sec =
- apply_offset(year, mon, day, hour, min, sec, zone_offset(zone))
+ apply_offset(year, mon, day, hour, min, sec, off)
t = self.utc(year, mon, day, hour, min, sec)
- t.localtime if !zone_utc?(zone)
+ force_zone!(t, zone, off)
t
else
raise ArgumentError.new("not RFC 2822 compliant date: #{date.inspect}")
@@ -471,18 +562,23 @@ class Time
#
# See #httpdate for more information on this format.
#
+ # require 'time'
+ #
+ # Time.httpdate("Thu, 06 Oct 2011 02:26:12 GMT")
+ # #=> 2011-10-06 02:26:12 UTC
+ #
# You must require 'time' to use this method.
#
def httpdate(date)
- if /\A\s*
+ if date.match?(/\A\s*
(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\x20
(\d{2})\x20
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20
(\d{4})\x20
(\d{2}):(\d{2}):(\d{2})\x20
GMT
- \s*\z/ix =~ date
- self.rfc2822(date)
+ \s*\z/ix)
+ self.rfc2822(date).utc
elsif /\A\s*
(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),\x20
(\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d)\x20
@@ -511,25 +607,30 @@ class Time
end
#
- # Parses +date+ as a dateTime defined by the XML Schema and converts it to
+ # Parses +time+ as a dateTime defined by the XML Schema and converts it to
# a Time object. The format is a restricted version of the format defined
# by ISO 8601.
#
- # ArgumentError is raised if +date+ is not compliant with the format or if
- # the Time class cannot represent specified date.
+ # ArgumentError is raised if +time+ is not compliant with the format or if
+ # the Time class cannot represent the specified time.
#
# See #xmlschema for more information on this format.
#
+ # require 'time'
+ #
+ # Time.xmlschema("2011-10-05T22:26:12-04:00")
+ # #=> 2011-10-05 22:26:12-04:00
+ #
# You must require 'time' to use this method.
#
- def xmlschema(date)
+ def xmlschema(time)
if /\A\s*
(-?\d+)-(\d\d)-(\d\d)
T
(\d\d):(\d\d):(\d\d)
(\.\d+)?
- (Z|[+-]\d\d:\d\d)?
- \s*\z/ix =~ date
+ (Z|[+-]\d\d(?::?\d\d)?)?
+ \s*\z/ix =~ time
year = $1.to_i
mon = $2.to_i
day = $3.to_i
@@ -542,14 +643,17 @@ class Time
end
if $8
zone = $8
+ off = zone_offset(zone)
year, mon, day, hour, min, sec =
- apply_offset(year, mon, day, hour, min, sec, zone_offset(zone))
- self.utc(year, mon, day, hour, min, sec, usec)
+ apply_offset(year, mon, day, hour, min, sec, off)
+ t = self.utc(year, mon, day, hour, min, sec, usec)
+ force_zone!(t, zone, off)
+ t
else
self.local(year, mon, day, hour, min, sec, usec)
end
else
- raise ArgumentError.new("invalid date: #{date.inspect}")
+ raise ArgumentError.new("invalid xmlschema format: #{time.inspect}")
end
end
alias iso8601 xmlschema
@@ -564,31 +668,18 @@ class Time
#
# If +self+ is a UTC time, -0000 is used as zone.
#
+ # require 'time'
+ #
+ # t = Time.now
+ # t.rfc2822 # => "Wed, 05 Oct 2011 22:26:12 -0400"
+ #
# You must require 'time' to use this method.
#
def rfc2822
- sprintf('%s, %02d %s %0*d %02d:%02d:%02d ',
- RFC2822_DAY_NAME[wday],
- day, RFC2822_MONTH_NAME[mon-1], year < 0 ? 5 : 4, year,
- hour, min, sec) +
- if utc?
- '-0000'
- else
- off = utc_offset
- sign = off < 0 ? '-' : '+'
- sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60))
- end
+ strftime('%a, %d %b %Y %T ') << (utc? ? '-0000' : strftime('%z'))
end
alias rfc822 rfc2822
- RFC2822_DAY_NAME = [
- 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
- ]
- RFC2822_MONTH_NAME = [
- 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
- 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
- ]
-
#
# Returns a string which represents the time as RFC 1123 date of HTTP-date
# defined by RFC 2616:
@@ -597,40 +688,47 @@ class Time
#
# Note that the result is always UTC (GMT).
#
+ # require 'time'
+ #
+ # t = Time.now
+ # t.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT"
+ #
# You must require 'time' to use this method.
#
def httpdate
- t = dup.utc
- sprintf('%s, %02d %s %0*d %02d:%02d:%02d GMT',
- RFC2822_DAY_NAME[t.wday],
- t.day, RFC2822_MONTH_NAME[t.mon-1], t.year < 0 ? 5 : 4, t.year,
- t.hour, t.min, t.sec)
+ getutc.strftime('%a, %d %b %Y %T GMT')
end
- #
- # Returns a string which represents the time as a dateTime defined by XML
- # Schema:
- #
- # CCYY-MM-DDThh:mm:ssTZD
- # CCYY-MM-DDThh:mm:ss.sssTZD
- #
- # where TZD is Z or [+-]hh:mm.
- #
- # If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
- #
- # +fractional_digits+ specifies a number of digits to use for fractional
- # seconds. Its default value is 0.
- #
- # You must require 'time' to use this method.
- #
- def xmlschema(fraction_digits=0)
- fraction_digits = fraction_digits.to_i
- s = strftime("%FT%T")
- if fraction_digits > 0
- s << strftime(".%#{fraction_digits}N")
+ unless method_defined?(:xmlschema)
+ #
+ # Returns a string which represents the time as a dateTime defined by XML
+ # Schema:
+ #
+ # CCYY-MM-DDThh:mm:ssTZD
+ # CCYY-MM-DDThh:mm:ss.sssTZD
+ #
+ # where TZD is Z or [+-]hh:mm.
+ #
+ # If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
+ #
+ # +fraction_digits+ specifies a number of digits to use for fractional
+ # seconds. Its default value is 0.
+ #
+ # require 'time'
+ #
+ # t = Time.now
+ # t.iso8601 # => "2011-10-05T22:26:12-04:00"
+ #
+ # You must require 'time' to use this method.
+ #
+ def xmlschema(fraction_digits=0)
+ fraction_digits = fraction_digits.to_i
+ s = strftime("%FT%T")
+ if fraction_digits > 0
+ s << strftime(".%#{fraction_digits}N")
+ end
+ s << (utc? ? 'Z' : strftime("%:z"))
end
- s << (utc? ? 'Z' : strftime("%:z"))
end
- alias iso8601 xmlschema
+ alias iso8601 xmlschema unless method_defined?(:iso8601)
end
-