class Time

公共类方法

httpdate(date) 点击切换源代码

date 解析为 RFC 2616 定义的 HTTP-date 并将其转换为 Time 对象。

如果 date 不符合 RFC 2616 或 Time 类无法表示指定的日期,则会引发 ArgumentError。

有关此格式的更多信息,请参阅 httpdate

require 'time'

Time.httpdate("Thu, 06 Oct 2011 02:26:12 GMT")
#=> 2011-10-06 02:26:12 UTC

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 569
def httpdate(date)
  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)
    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
         (\d\d):(\d\d):(\d\d)\x20
         GMT
         \s*\z/ix =~ date
    year = $3.to_i
    if year < 50
      year += 2000
    else
      year += 1900
    end
    self.utc(year, $2, $1.to_i, $4.to_i, $5.to_i, $6.to_i)
  elsif /\A\s*
         (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\x20
         (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20
         (\d\d|\x20\d)\x20
         (\d\d):(\d\d):(\d\d)\x20
         (\d{4})
         \s*\z/ix =~ date
    self.utc($6.to_i, MonthValue[$1.upcase], $2.to_i,
             $3.to_i, $4.to_i, $5.to_i)
  else
    raise ArgumentError.new("not RFC 2616 compliant date: #{date.inspect}")
  end
end
iso8601(time)
别名:xmlschema
parse(date, now=self.now) { |year| ... } 点击切换源代码

接收 Time 的字符串表示形式,并尝试使用启发式方法解析它。

此方法**不**作为验证器。如果输入字符串不严格匹配有效格式,您可能会得到一个神秘的结果。应尽可能考虑使用 Time.strptime 而不是此方法。

require 'time'

Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500

日期中任何缺失的部分都会根据当前日期进行推断。

require 'time'

# assuming the current date is "2011-10-31"
Time.parse("12:00") #=> 2011-10-31 12:00:00 -0500

我们可以通过传递第二个对象来更改用于推断缺失元素的日期,该对象可以响应 mon、day 和 year,例如 Date、Time 或 DateTime。我们也可以使用我们自己的对象。

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

如果给出了代码块,则 date 中描述的年份将由代码块转换。这是专门为处理两位数年份而设计的。例如,如果您想将 70 之前的所有两位数年份视为 2000+ 年,您可以这样写

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

如果给定时间的较高部分损坏或缺失,则会用 now 的相应部分填充。对于较低的部分,如果损坏或缺失,则假定最小值为(1 或 0)。例如

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

由于世界各地本地定义的时区缩写之间存在大量冲突,因此此方法并非旨在理解所有这些缩写。例如,缩写“CST”被各种用作

-06:00 in America/Chicago,
-05:00 in America/Havana,
+08:00 in Asia/Harbin,
+09:30 in Australia/Darwin,
+10:30 in Australia/Adelaide,
etc.

基于此事实,此方法仅按名称顺序理解 RFC 822 中描述的时区缩写和系统时区。(即,RFC 822 中的定义会覆盖系统时区定义。)系统时区取自 Time.local(year, 1, 1).zoneTime.local(year, 7, 1).zone。如果提取的时区缩写与它们中的任何一个都不匹配,则会忽略它,并将给定时间视为本地时间。

如果 Date._parse 无法从 date 中提取信息,或者 Time 类无法表示指定的日期,则会引发 ArgumentError。

此方法可用作其他解析方法的故障保护,例如

Time.rfc2822(date) rescue Time.parse(date)
Time.httpdate(date) rescue Time.parse(date)
Time.xmlschema(date) rescue Time.parse(date)

但应检查 Time.parse 的失败情况。

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 382
def parse(date, now=self.now)
  comp = !block_given?
  d = Date._parse(date, comp)
  year = d[:year]
  year = yield(year) if year && !comp
  make_time(date, year, d[:yday], d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
end
rfc2822(date) 点击切换源代码

date 解析为 RFC 2822 定义的日期时间并将其转换为 Time 对象。该格式与 RFC 822 定义并由 RFC 1123 更新的日期格式相同。

如果 date 不符合 RFC 2822 或 Time 类无法表示指定的日期,则会引发 ArgumentError。

有关此格式的更多信息,请参阅 rfc2822

require 'time'

Time.rfc2822("Wed, 05 Oct 2011 22:26:12 -0400")
#=> 2010-10-05 22:26:12 -0400

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 511
def rfc2822(date)
  if /\A\s*
      (?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)?
      (\d{1,2})\s+
      (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\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

    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, off)
    t = self.utc(year, mon, day, hour, min, sec)
    force_zone!(t, zone, off)
    t
  else
    raise ArgumentError.new("not RFC 2822 compliant date: #{date.inspect}")
  end
end
别名:rfc822
rfc822(date)
别名:rfc2822
strptime(date, format, now=self.now) { |year| ... } 点击切换源代码

parse 的工作方式类似,但不是使用启发式方法来检测输入字符串的格式,而是提供第二个参数来描述字符串的格式。

如果日期或格式无效,则会引发 ArgumentError。

如果给出了代码块,则 date 中描述的年份将由代码块转换。例如

Time.strptime(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}

以下是格式化选项的列表

%a

工作日名称的缩写(“Sun”)

%A

工作日的全名(“Sunday”)

%b

月份名称的缩写(“Jan”)

%B

月份的全名(“January”)

%c

首选的本地日期和时间表示

%C

世纪(2009 年为 20)

%d

月份中的日期(01..31)

%D

日期(%m/%d/%y)

%e

月份中的日期,用空格填充( 1..31)

%F

等效于 %Y-%m-%d(ISO 8601 日期格式)

%g

商业年的最后两位数字

%G

根据 ISO-8601 的基于周的年份(第 1 周从星期一开始,包括 1 月 4 日)

%h

等效于 %b

%H

一天中的小时,24 小时制(00..23)

%I

一天中的小时,12 小时制(01..12)

%j

一年中的日期(001..366)

%k

小时,24 小时制,用空格填充( 0..23)

%l

小时,12 小时制,用空格填充( 0..12)

%L

秒的毫秒(000..999)

%m

一年中的月份(01..12)

%M

小时中的分钟(00..59)

%n

换行符 (n)

%N

秒的小数位数

%p

子午线指示符(“AM”或“PM”)

%P

子午线指示符(“am”或“pm”)

%r

时间,12 小时制(与 %I:%M:%S %p 相同)

%R

时间,24 小时制(%H:%M)

%s

自 1970-01-01 00:00:00 UTC 以来的秒数。

%S

分钟中的秒数(00..60)

%t

制表符 (t)

%T

时间,24 小时制(%H:%M:%S)

%u

工作日作为十进制数,星期一为 1。(1..7)

%U

当前年份的周数,从第一个星期日作为第一周的第一天开始(00..53)

%v

VMS 日期(%e-%b-%Y)

%V

根据 ISO 8601 的年份周数(01..53)

%W

当前年份的周数,从第一个星期一作为第一周的第一天开始(00..53)

%w

星期几(星期日为 0,0..6)

%x

仅表示日期的首选表示形式,没有时间

%X

仅表示时间的首选表示形式,没有日期

%y

没有世纪的年份(00..99)

%Y

可能包含世纪的年份(如果提供)

%z

时区作为与 UTC 的小时偏移量(例如 +0900)

%Z

时区名称

%%

文字“%”字符

%+

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

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 459
def strptime(date, format, now=self.now)
  d = Date._strptime(date, format)
  raise ArgumentError, "invalid date or strptime format - '#{date}' '#{format}'" unless d
  if seconds = d[:seconds]
    if sec_fraction = d[:sec_fraction]
      usec = sec_fraction * 1000000
      usec *= -1 if seconds < 0
    else
      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?
    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
xmlschema(time) 点击切换源代码

time 解析为 XML Schema 定义的 dateTime,并将其转换为 Time 对象。该格式是 ISO 8601 定义的格式的受限版本。

如果 time 不符合该格式,或者 Time 类无法表示指定的时间,则会引发 ArgumentError。

有关此格式的更多信息,请参阅 xmlschema

require 'time'

Time.xmlschema("2011-10-05T22:26:12-04:00")
#=> 2011-10-05 22:26:12-04:00

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 623
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 =~ time
    year = $1.to_i
    mon = $2.to_i
    day = $3.to_i
    hour = $4.to_i
    min = $5.to_i
    sec = $6.to_i
    usec = 0
    if $7
      usec = Rational($7) * 1000000
    end
    if $8
      zone = $8
      off = zone_offset(zone)
      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)
      force_zone!(t, zone, off)
      t
    else
      self.local(year, mon, day, hour, min, sec, usec)
    end
  else
    raise ArgumentError.new("invalid xmlschema format: #{time.inspect}")
  end
end
别名:iso8601
zone_offset(zone, year=self.now.year) 点击切换源代码

返回指定时区与 UTC 之间的秒数差。

包括分钟的数字时区(如 -10:00+1330)以及更简单的仅包含小时的时区(如 -10+13)都可以使用。

还支持 ZoneOffset 中列出的文本时区。

如果时区与上述任何一个都不匹配,zone_offset 将检查本地时区(包括和不包括潜在的夏令时更改)是否与 zone 匹配。为 year 指定一个值将更改用于查找本地时区的年份。

如果 zone_offset 无法确定偏移量,则将返回 nil。

require 'time'

Time.zone_offset("EST") #=> -18000

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 83
def zone_offset(zone, year=self.now.year)
  off = nil
  zone = zone.upcase
  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
  end
  off
end

公共实例方法

httpdate() 点击切换源代码

返回一个字符串,该字符串表示为 RFC 2616 定义的 HTTP-date 的 RFC 1123 日期的时间

day-of-week, DD month-name CCYY hh:mm:ss GMT

请注意,结果始终为 UTC (GMT)。

require 'time'

t = Time.now
t.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT"

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 695
def httpdate
  getutc.strftime('%a, %d %b %Y %T GMT')
end
iso8601(fraction_digits=0)
别名:xmlschema
rfc2822() 点击切换源代码

返回一个字符串,该字符串表示为 RFC 2822 定义的日期时间

day-of-week, DD month-name CCYY hh:mm:ss zone

其中 zone 为 [+-]hhmm。

如果 self 是 UTC 时间,则使用 -0000 作为 zone。

require 'time'

t = Time.now
t.rfc2822  # => "Wed, 05 Oct 2011 22:26:12 -0400"

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 675
def rfc2822
  strftime('%a, %d %b %Y %T ') << (utc? ? '-0000' : strftime('%z'))
end
别名:rfc822
rfc822()
别名:rfc2822
xmlschema(fraction_digits=0) 点击切换源代码

返回一个字符串,该字符串表示为 XML Schema 定义的 dateTime

CCYY-MM-DDThh:mm:ssTZD
CCYY-MM-DDThh:mm:ss.sssTZD

其中 TZD 为 Z 或 [+-]hh:mm。

如果 self 是 UTC 时间,则使用 Z 作为 TZD。否则使用 [+-]hh:mm。

fraction_digits 指定用于小数秒的位数。其默认值为 0。

require 'time'

t = Time.now
t.iso8601  # => "2011-10-05T22:26:12-04:00"

您必须 require ‘time’ 才能使用此方法。

# File time.rb, line 721
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
别名也为:iso8601