Converted RD to RDoc, with some changes/additions.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3391 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
064f07ace5
commit
b95357be1a
337
lib/time.rb
337
lib/time.rb
@ -1,44 +1,51 @@
|
|||||||
|
|
||||||
|
#
|
||||||
|
# == Introduction
|
||||||
|
#
|
||||||
|
# This library extends the Time class:
|
||||||
|
# * conversion between date string and time object.
|
||||||
|
# * date-time defined by RFC 2822
|
||||||
|
# * HTTP-date defined by RFC 2616
|
||||||
|
# * dateTime defined by XML Schema Part 2: Datatypes (ISO 8601)
|
||||||
|
# * various formats handled by ParseDate (string to time only)
|
||||||
|
#
|
||||||
|
# == Design Issues
|
||||||
|
#
|
||||||
|
# === Specialized interface
|
||||||
|
#
|
||||||
|
# This library provides methods dedicated to special puposes:
|
||||||
|
# * RFC 2822, RFC 2616 and XML Schema.
|
||||||
|
# * They makes usual life easier.
|
||||||
|
#
|
||||||
|
# === Doesn't depend on strftime
|
||||||
|
#
|
||||||
|
# This library doesn't use +strftime+. Especially #rfc2822 doesn't depend
|
||||||
|
# on +strftime+ because:
|
||||||
|
#
|
||||||
|
# * %a and %b are locale sensitive
|
||||||
|
#
|
||||||
|
# Since they are locale sensitive, they may be replaced to
|
||||||
|
# invalid weekday/month name in some locales.
|
||||||
|
# Since ruby-1.6 doesn't invoke setlocale by default,
|
||||||
|
# the problem doesn't arise until some external library invokes setlocale.
|
||||||
|
# Ruby/GTK is the example of such library.
|
||||||
|
#
|
||||||
|
# * %z is not portable
|
||||||
|
#
|
||||||
|
# %z is required to generate zone in date-time of RFC 2822
|
||||||
|
# but it is not portable.
|
||||||
|
#
|
||||||
|
# == Revision Information
|
||||||
|
#
|
||||||
# $Id$
|
# $Id$
|
||||||
|
#
|
||||||
|
|
||||||
require 'parsedate'
|
require 'parsedate'
|
||||||
|
|
||||||
=begin
|
#
|
||||||
= time
|
# Implements the extensions to the Time class that are described in the
|
||||||
|
# documentation for the time.rb library.
|
||||||
This library extends Time class:
|
#
|
||||||
* conversion between date string and time object.
|
|
||||||
* date-time defined by RFC 2822
|
|
||||||
* HTTP-date defined by RFC 2616
|
|
||||||
* dateTime defined by XML Schema Part 2: Datatypes (ISO 8601)
|
|
||||||
* various format handled by ParseDate (string to time only)
|
|
||||||
|
|
||||||
== Design Issue
|
|
||||||
|
|
||||||
* specialized interface
|
|
||||||
|
|
||||||
This library provides methods dedicated to special puposes:
|
|
||||||
RFC 2822, RFC 2616 and XML Schema.
|
|
||||||
They makes usual life easier.
|
|
||||||
|
|
||||||
* doesn't depend on strftime
|
|
||||||
|
|
||||||
This library doesn't use strftime.
|
|
||||||
Especially Time#rfc2822 doesn't depend on strftime because:
|
|
||||||
|
|
||||||
* %a and %b are locale sensitive
|
|
||||||
|
|
||||||
Since they are locale sensitive, they may be replaced to
|
|
||||||
invalid weekday/month name in some locales.
|
|
||||||
Since ruby-1.6 doesn't invoke setlocale by default,
|
|
||||||
the problem doesn't arise until some external library invokes setlocale.
|
|
||||||
Ruby/GTK is the example of such library.
|
|
||||||
|
|
||||||
* %z is not portable
|
|
||||||
|
|
||||||
%z is required to generate zone in date-time of RFC 2822
|
|
||||||
but it is not portable.
|
|
||||||
=end
|
|
||||||
|
|
||||||
class Time
|
class Time
|
||||||
class << Time
|
class << Time
|
||||||
|
|
||||||
@ -76,63 +83,56 @@ class Time
|
|||||||
off
|
off
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
#
|
||||||
== class methods
|
# Parses +date+ using ParseDate.parsedate and converts it to a Time object.
|
||||||
|
#
|
||||||
--- Time.parse(date, now=Time.now)
|
# If a block is given, the year described in +date+ is converted by the
|
||||||
--- Time.parse(date, now=Time.now) {|year| year}
|
# block. For example:
|
||||||
parses ((|date|)) using ParseDate.parsedate and converts it to a
|
#
|
||||||
Time object.
|
# Time.parse(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
|
||||||
|
#
|
||||||
If a block is given, the year described in ((|date|)) is converted
|
# If the upper components of the given time are broken or missing, they are
|
||||||
by the block. For example:
|
# supplied with those of +now+. For the lower components, the minimum
|
||||||
|
# values (1 or 0) are assumed if broken or missing. For example:
|
||||||
Time.parse(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
|
#
|
||||||
|
# # Suppose it is "Thu Nov 29 14:33:20 GMT 2001" now and
|
||||||
If the upper components of the given time are broken or missing,
|
# # your timezone is GMT:
|
||||||
they are supplied with those of ((|now|)). For the lower
|
# Time.parse("16:30") #=> Thu Nov 29 16:30:00 GMT 2001
|
||||||
components, the minimum values (1 or 0) are assumed if broken or
|
# Time.parse("7/23") #=> Mon Jul 23 00:00:00 GMT 2001
|
||||||
missing. For example:
|
# Time.parse("2002/1") #=> Tue Jan 01 00:00:00 GMT 2002
|
||||||
|
#
|
||||||
# Suppose it is "Thu Nov 29 14:33:20 GMT 2001" now and
|
# Since there are numerous conflicts among locally defined timezone
|
||||||
# your timezone is GMT:
|
# abbreviations all over the world, this method is not made to
|
||||||
Time.parse("16:30") #=> Thu Nov 29 16:30:00 GMT 2001
|
# understand all of them. For example, the abbreviation "CST" is
|
||||||
Time.parse("7/23") #=> Mon Jul 23 00:00:00 GMT 2001
|
# used variously as:
|
||||||
Time.parse("2002/1") #=> Tue Jan 01 00:00:00 GMT 2002
|
#
|
||||||
|
# -06:00 in America/Chicago,
|
||||||
Since there are numerous conflicts among locally defined timezone
|
# -05:00 in America/Havana,
|
||||||
abbreviations all over the world, this method is not made to
|
# +08:00 in Asia/Harbin,
|
||||||
understand all of them. For example, the abbreviation "CST" is
|
# +09:30 in Australia/Darwin,
|
||||||
used variously as:
|
# +10:30 in Australia/Adelaide,
|
||||||
|
# etc.
|
||||||
-06:00 in America/Chicago,
|
#
|
||||||
-05:00 in America/Havana,
|
# Based on the fact, this method only understands the timezone
|
||||||
+08:00 in Asia/Harbin,
|
# abbreviations described in RFC 822 and the system timezone, in the
|
||||||
+09:30 in Australia/Darwin,
|
# order named. (i.e. a definition in RFC 822 overrides the system
|
||||||
+10:30 in Australia/Adelaide,
|
# timezone definition.) The system timezone is taken from
|
||||||
etc.
|
# <tt>Time.local(year, 1, 1).zone</tt> and
|
||||||
|
# <tt>Time.local(year, 7, 1).zone</tt>.
|
||||||
Based on the fact, this method only understands the timezone
|
# If the extracted timezone abbreviation does not match any of them,
|
||||||
abbreviations described in RFC 822 and the system timezone, in the
|
# it is ignored and the given time is regarded as a local time.
|
||||||
order named. (i.e. a definition in RFC 822 overrides the system
|
#
|
||||||
timezone definition) The system timezone is taken from
|
# ArgumentError is raised if ParseDate cannot extract information from
|
||||||
(({Time.local(year, 1, 1).zone})) and
|
# +date+ or Time class cannot represent specified date.
|
||||||
(({Time.local(year, 7, 1).zone})).
|
#
|
||||||
If the extracted timezone abbreviation does not match any of them,
|
# This method can be used as fail-safe for other parsing methods as:
|
||||||
it is ignored and the given time is regarded as a local time.
|
#
|
||||||
|
# Time.rfc2822(date) rescue Time.parse(date)
|
||||||
ArgumentError is raised if ParseDate cannot extract
|
# Time.httpdate(date) rescue Time.parse(date)
|
||||||
information from ((|date|))
|
# Time.xmlschema(date) rescue Time.parse(date)
|
||||||
or Time class cannot represent specified date.
|
#
|
||||||
|
# A failure for Time.parse should be checked, though.
|
||||||
This method can be used as fail-safe for other parsing methods as:
|
#
|
||||||
|
|
||||||
Time.rfc2822(date) rescue Time.parse(date)
|
|
||||||
Time.httpdate(date) rescue Time.parse(date)
|
|
||||||
Time.xmlschema(date) rescue Time.parse(date)
|
|
||||||
|
|
||||||
A failure for Time.parse should be checked, though.
|
|
||||||
=end
|
|
||||||
def parse(date, now=Time.now)
|
def parse(date, now=Time.now)
|
||||||
year, mon, day, hour, min, sec, zone, _ = ParseDate.parsedate(date)
|
year, mon, day, hour, min, sec, zone, _ = ParseDate.parsedate(date)
|
||||||
year = yield year if year && block_given?
|
year = yield year if year && block_given?
|
||||||
@ -172,17 +172,16 @@ class Time
|
|||||||
'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' =>10, 'NOV' =>11, 'DEC' =>12
|
'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' =>10, 'NOV' =>11, 'DEC' =>12
|
||||||
}
|
}
|
||||||
|
|
||||||
=begin
|
#
|
||||||
--- Time.rfc2822(date)
|
# Parses +date+ as date-time defined by RFC 2822 and converts it to a Time
|
||||||
--- Time.rfc822(date)
|
# object. The format is identical to the date format defined by RFC 822 and
|
||||||
parses ((|date|)) as date-time defined by RFC 2822 and converts it to a
|
# updated by RFC 1123.
|
||||||
Time object.
|
#
|
||||||
The format is identical to the date format defined by RFC 822 and
|
# ArgumentError is raised if +date+ is not compliant with RFC 2822
|
||||||
updated by RFC 1123.
|
# or Time class cannot represent specified date.
|
||||||
|
#
|
||||||
ArgumentError is raised if ((|date|)) is not compliant with RFC 2822
|
# See #rfc2822 for more information on this format.
|
||||||
or Time class cannot represent specified date.
|
#
|
||||||
=end
|
|
||||||
def rfc2822(date)
|
def rfc2822(date)
|
||||||
if /\A\s*
|
if /\A\s*
|
||||||
(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)?
|
(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)?
|
||||||
@ -222,14 +221,15 @@ class Time
|
|||||||
end
|
end
|
||||||
alias rfc822 rfc2822
|
alias rfc822 rfc2822
|
||||||
|
|
||||||
=begin
|
#
|
||||||
--- Time.httpdate(date)
|
# Parses +date+ as HTTP-date defined by RFC 2616 and converts it to a Time
|
||||||
parses ((|date|)) as HTTP-date defined by RFC 2616 and converts it to a
|
# object.
|
||||||
Time object.
|
#
|
||||||
|
# ArgumentError is raised if +date+ is not compliant with RFC 2616 or Time
|
||||||
ArgumentError is raised if ((|date|)) is not compliant with RFC 2616
|
# class cannot represent specified date.
|
||||||
or Time class cannot represent specified date.
|
#
|
||||||
=end
|
# See #httpdate for more information on this format.
|
||||||
|
#
|
||||||
def httpdate(date)
|
def httpdate(date)
|
||||||
if /\A\s*
|
if /\A\s*
|
||||||
(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\x20
|
(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\x20
|
||||||
@ -261,16 +261,16 @@ class Time
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
#
|
||||||
--- Time.xmlschema(date)
|
# Parses +date+ as dateTime defined by XML Schema and converts it to a Time
|
||||||
--- Time.iso8601(date)
|
# object. The format is restricted version of the format defined by ISO
|
||||||
parses ((|date|)) as dateTime defined by XML Schema and
|
# 8601.
|
||||||
converts it to a Time object.
|
#
|
||||||
The format is restricted version of the format defined by ISO 8601.
|
# ArgumentError is raised if +date+ is not compliant with the format or Time
|
||||||
|
# class cannot represent specified date.
|
||||||
ArgumentError is raised if ((|date|)) is not compliant with the format
|
#
|
||||||
or Time class cannot represent specified date.
|
# See #xmlschema for more information on this format.
|
||||||
=end
|
#
|
||||||
def xmlschema(date)
|
def xmlschema(date)
|
||||||
if /\A\s*
|
if /\A\s*
|
||||||
(-?\d+)-(\d\d)-(\d\d)
|
(-?\d+)-(\d\d)-(\d\d)
|
||||||
@ -291,31 +291,17 @@ class Time
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
alias iso8601 xmlschema
|
alias iso8601 xmlschema
|
||||||
end
|
end # class << self
|
||||||
|
|
||||||
=begin
|
#
|
||||||
== methods
|
# Returns a string which represents the time as date-time defined by RFC 2822:
|
||||||
=end
|
#
|
||||||
|
# day-of-week, DD month-name CCYY hh:mm:ss zone
|
||||||
=begin
|
#
|
||||||
--- Time#rfc2822
|
# where zone is [+-]hhmm.
|
||||||
--- Time#rfc822
|
#
|
||||||
returns a string which represents the time as date-time defined by RFC 2822:
|
# If +self+ is a UTC time, -0000 is used as zone.
|
||||||
|
#
|
||||||
day-of-week, DD month-name CCYY hh:mm:ss zone
|
|
||||||
|
|
||||||
where zone is [+-]hhmm.
|
|
||||||
|
|
||||||
If self is a UTC time, -0000 is used as zone.
|
|
||||||
=end
|
|
||||||
|
|
||||||
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'
|
|
||||||
]
|
|
||||||
def rfc2822
|
def rfc2822
|
||||||
sprintf('%s, %02d %s %d %02d:%02d:%02d ',
|
sprintf('%s, %02d %s %d %02d:%02d:%02d ',
|
||||||
RFC2822_DAY_NAME[wday],
|
RFC2822_DAY_NAME[wday],
|
||||||
@ -331,15 +317,22 @@ class Time
|
|||||||
end
|
end
|
||||||
alias rfc822 rfc2822
|
alias rfc822 rfc2822
|
||||||
|
|
||||||
=begin
|
RFC2822_DAY_NAME = [
|
||||||
--- Time#httpdate
|
'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
|
||||||
returns a string which represents the time as rfc1123-date of HTTP-date
|
]
|
||||||
defined by RFC 2616:
|
RFC2822_MONTH_NAME = [
|
||||||
|
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
||||||
|
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
|
||||||
|
]
|
||||||
|
|
||||||
day-of-week, DD month-name CCYY hh:mm:ss GMT
|
#
|
||||||
|
# Returns a string which represents the time as rfc1123-date of HTTP-date
|
||||||
Note that the result is always UTC (GMT).
|
# defined by RFC 2616:
|
||||||
=end
|
#
|
||||||
|
# day-of-week, DD month-name CCYY hh:mm:ss GMT
|
||||||
|
#
|
||||||
|
# Note that the result is always UTC (GMT).
|
||||||
|
#
|
||||||
def httpdate
|
def httpdate
|
||||||
t = dup.utc
|
t = dup.utc
|
||||||
sprintf('%s, %02d %s %d %02d:%02d:%02d GMT',
|
sprintf('%s, %02d %s %d %02d:%02d:%02d GMT',
|
||||||
@ -348,24 +341,20 @@ class Time
|
|||||||
t.hour, t.min, t.sec)
|
t.hour, t.min, t.sec)
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
#
|
||||||
--- Time#xmlschema([fractional_seconds])
|
# Returns a string which represents the time as dateTime defined by XML
|
||||||
--- Time#iso8601([fractional_seconds])
|
# Schema:
|
||||||
returns a string which represents the time as dateTime
|
#
|
||||||
defined by XML Schema:
|
# CCYY-MM-DDThh:mm:ssTZD
|
||||||
|
# CCYY-MM-DDThh:mm:ss.sssTZD
|
||||||
CCYY-MM-DDThh:mm:ssTZD
|
#
|
||||||
CCYY-MM-DDThh:mm:ss.sssTZD
|
# where TZD is Z or [+-]hh:mm.
|
||||||
|
#
|
||||||
where TZD is Z or [+-]hh:mm.
|
# If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
|
||||||
|
#
|
||||||
If self is a UTC time, Z is used as TZD.
|
# +fractional_seconds+ specifies a number of digits of fractional seconds.
|
||||||
[+-]hh:mm is used otherwise.
|
# Its default value os 0.
|
||||||
|
#
|
||||||
((|fractional_seconds|)) specify a number of digits of
|
|
||||||
fractional seconds.
|
|
||||||
The default value of ((|fractional_seconds|)) is 0.
|
|
||||||
=end
|
|
||||||
def xmlschema(fraction_digits=0)
|
def xmlschema(fraction_digits=0)
|
||||||
sprintf('%d-%02d-%02dT%02d:%02d:%02d',
|
sprintf('%d-%02d-%02dT%02d:%02d:%02d',
|
||||||
year, mon, day, hour, min, sec) +
|
year, mon, day, hour, min, sec) +
|
||||||
@ -390,7 +379,7 @@ end
|
|||||||
if __FILE__ == $0
|
if __FILE__ == $0
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
|
|
||||||
class TimeExtentionTest < Test::Unit::TestCase
|
class TimeExtentionTest < Test::Unit::TestCase # :nodoc:
|
||||||
def test_rfc822
|
def test_rfc822
|
||||||
assert_equal(Time.utc(1976, 8, 26, 14, 30) + 4 * 3600,
|
assert_equal(Time.utc(1976, 8, 26, 14, 30) + 4 * 3600,
|
||||||
Time.rfc2822("26 Aug 76 14:30 EDT"))
|
Time.rfc2822("26 Aug 76 14:30 EDT"))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user