class Time - time: Ruby Standard Library Documentation

# class Time

### Public Class Methods

httpdate(date) click to toggle source

Parses `date` as an HTTP-date defined by RFC 2616 and converts it to a `Time` object.

ArgumentError is raised if `date` is not compliant with RFC 2616 or if the `Time` class cannot represent specified date.

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.

    # 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)
Alias for: xmlschema
parse(date, now=self.now) { |year| ... } click to toggle source

Takes a string representation of a `Time` and attempts to parse it using a heuristic.

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

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:

    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 understand all of them. For example, the abbreviation “CST” is used variously as:

    -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.

Based on this fact, this method only understands the time zone abbreviations described in RFC 822 and the system time zone, in the order named. (i.e. a definition in RFC 822 overrides the system time zone definition.) The system time zone is taken from `Time.local(year, 1, 1).zone` and `Time.local(year, 7, 1).zone`. If the extracted time zone abbreviation does not match any of them, it is ignored and the given time is regarded as a local time.

ArgumentError is raised if Date._parse cannot extract information from `date` or if the `Time` class cannot represent specified date.

This method can be used as a 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 of `Time.parse` should be checked, though.

You must require ‘time’ to use this method.

    # 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) click to toggle source

Parses `date` as date-time defined by RFC 2822 and converts it to a `Time` object. The format is identical to the date format defined by RFC 822 and updated by RFC 1123.

ArgumentError is raised if `date` is not compliant with RFC 2822 or if the `Time` class cannot represent specified date.

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.

    # 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

Also aliased as: rfc822
rfc822(date)
Alias for: rfc2822
strptime(date, format, now=self.now) { |year| ... } click to toggle source

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 formatting options:

%a

  The abbreviated weekday name (“Sun”)

%A

  The full weekday name (“Sunday”)

%b

  The abbreviated month name (“Jan”)

%B

  The full month name (“January”)

%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)

%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)

%j

  Day of the year (001..366)

%k

  hour, 24-hour clock, blank-padded ( 0..23)

%l

  hour, 12-hour clock, blank-padded ( 0..12)

%L

  Millisecond of the second (000..999)

%m

  Month of the year (01..12)

%M

  Minute of the hour (00..59)

%n

  Newline (n)

%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)

%R

  time, 24-hour (%H:%M)

%s

  Number of seconds since 1970-01-01 00:00:00 UTC.

%S

  Second of the minute (00..60)

%t

  Tab character (t)

%T

  time, 24-hour (%H:%M:%S)

%u

  Day of the week as a decimal, Monday being 1. (1..7)

%U

  Week number of the current year, starting with the first Sunday as the first day of the first week (00..53)

%v

  VMS date (%e-%b-%Y)

%V

  Week number of year according to ISO 8601 (01..53)

%W

  Week number of the current year, starting with the first Monday as the first day of the first week (00..53)

%w

  Day of the week (Sunday is 0, 0..6)

%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 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.

    # 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) click to toggle source

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 `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.

    # 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

Also aliased as: iso8601
zone_offset(zone, year=self.now.year) click to toggle source

Return the number of seconds the specified time zone differs from UTC.

Numeric time zones that include minutes, such as `-10:00` or `+1330` will work, as will simpler hour-only time zones like `-10` or `+13`.

Textual time zones listed in ZoneOffset are also supported.

If the time zone does not match any of the above, `zone_offset` will check if the local time zone (both with and without potential Daylight Saving Time changes being in effect) matches `zone`. Specifying a value for `year` will change the year used to find the local time zone.

If `zone_offset` is unable to determine the offset, nil will be returned.

    require 'time'

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

You must require ‘time’ to use this method.

    # 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

### Public Instance Methods

httpdate() click to toggle source

Returns a string which represents the time as RFC 1123 date of HTTP-date defined by RFC 2616:

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

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.

    # File time.rb, line 695
    def httpdate
      getutc.strftime('%a, %d %b %Y %T GMT')
    end

iso8601(fraction_digits=0)
Alias for: xmlschema
rfc2822() click to toggle source

Returns a string which represents the time as date-time defined by RFC 2822:

    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.

    require 'time'

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

You must require ‘time’ to use this method.

    # File time.rb, line 675
    def rfc2822
      strftime('%a, %d %b %Y %T ') << (utc? ? '-0000' : strftime('%z'))
    end

Also aliased as: rfc822
rfc822()
Alias for: rfc2822
xmlschema(fraction_digits=0) click to toggle source

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.

    # 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

Also aliased as: iso8601