Skip to content
On this page
guide · Ruby 4.0

Formats for Dates and Times

Several Ruby time-related classes have instance method strftime, which returns a formatted string representing all or part of a date or time:

Each of these methods takes optional argument format, which has zero or more embedded format specifications (see below).

Each of these methods returns the string resulting from replacing each format specification embedded in format with a string form of one or more parts of the date or time.

A simple example:

Example
Time.now.strftime('%H:%M:%S') # => "14:02:07"

A format specification has the form:

%[flags][width]conversion

It consists of:

  • A leading percent character.

  • Zero or more flags (each is a character).

  • An optional width specifier (an integer).

  • A conversion specifier (a character).

Except for the leading percent character, the only required part is the conversion specifier, so we begin with that.

Conversion Specifiers

Date (Year, Month, Day)

  • %Y - Year including century, zero-padded:

    Example
    Time.now.strftime('%Y')        # => "2022"
    Time.new(-1000).strftime('%Y') # => "-1000" # Before common era.
    Time.new(10000).strftime('%Y') # => "10000" # Far future.
    Time.new(10).strftime('%Y')    # => "0010"  # Zero-padded by default.
    
  • %y - Year without century, in range (0.99), zero-padded:

    Example
    Time.now.strftime('%y')    # => "22"
    Time.new(1).strftime('%y') # => "01" # Zero-padded by default.
    
  • %C - Century, zero-padded:

    Example
    Time.now.strftime('%C')        # => "20"
    Time.new(-1000).strftime('%C') # => "-10" # Before common era.
    Time.new(10000).strftime('%C') # => "100" # Far future.
    Time.new(100).strftime('%C')   # => "01"  # Zero-padded by default.
    
  • %m - Month of the year, in range (1..12), zero-padded:

    Example
    Time.new(2022, 1).strftime('%m')  # => "01" # Zero-padded by default.
    Time.new(2022, 12).strftime('%m') # => "12"
    
  • %B - Full month name, capitalized:

    Example
    Time.new(2022, 1).strftime('%B')  # => "January"
    Time.new(2022, 12).strftime('%B') # => "December"
    
  • %b - Abbreviated month name, capitalized:

    Example
    Time.new(2022, 1).strftime('%b')  # => "Jan"
    Time.new(2022, 12).strftime('%h') # => "Dec"
    
  • %h - Same as %b.

  • %d - Day of the month, in range (1..31), zero-padded:

    Example
    Time.new(2002, 1, 1).strftime('%d')  # => "01"
    Time.new(2002, 1, 31).strftime('%d') # => "31"
    
  • %e - Day of the month, in range (1..31), blank-padded:

    Example
    Time.new(2002, 1, 1).strftime('%e')  # => " 1"
    Time.new(2002, 1, 31).strftime('%e') # => "31"
    
  • %j - Day of the year, in range (1..366), zero-padded:

    Example
    Time.new(2002, 1, 1).strftime('%j')   # => "001"
    Time.new(2002, 12, 31).strftime('%j') # => "365"
    

Time (Hour, Minute, Second, Subsecond)

  • %H - Hour of the day, in range (0..23), zero-padded:

    Example
    Time.new(2022, 1, 1, 1).strftime('%H')  # => "01"
    Time.new(2022, 1, 1, 13).strftime('%H') # => "13"
    
  • %k - Hour of the day, in range (0..23), blank-padded:

    Example
    Time.new(2022, 1, 1, 1).strftime('%k')  # => " 1"
    Time.new(2022, 1, 1, 13).strftime('%k') # => "13"
    
  • %I - Hour of the day, in range (1..12), zero-padded:

    Example
    Time.new(2022, 1, 1, 1).strftime('%I')  # => "01"
    Time.new(2022, 1, 1, 13).strftime('%I') # => "01"
    
  • %l - Hour of the day, in range (1..12), blank-padded:

    Example
    Time.new(2022, 1, 1, 1).strftime('%l')  # => " 1"
    Time.new(2022, 1, 1, 13).strftime('%l') # => " 1"
    
  • %P - Meridian indicator, lowercase:

    Example
    Time.new(2022, 1, 1, 1).strftime('%P')  # => "am"
    Time.new(2022, 1, 1, 13).strftime('%P') # => "pm"
    
  • %p - Meridian indicator, uppercase:

    Example
    Time.new(2022, 1, 1, 1).strftime('%p')  # => "AM"
    Time.new(2022, 1, 1, 13).strftime('%p') # => "PM"
    
  • %M - Minute of the hour, in range (0..59), zero-padded:

    Example
    Time.new(2022, 1, 1, 1, 0, 0).strftime('%M') # => "00"
    
  • %S - Second of the minute in range (0..59), zero-padded:

    Example
    Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%S') # => "00"
    
  • %L - Millisecond of the second, in range (0..999), zero-padded:

    Example
    Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%L') # => "000"
    
  • %N - Fractional seconds, default width is 9 digits (nanoseconds):

    Example
    t = Time.now       # => 2022-06-29 07:10:20.3230914 -0500
    t.strftime('%N')   # => "323091400"                  # Default.
    

    Use width specifiers to adjust units:

    Example
    t.strftime('%3N')  # => "323"                      # Milliseconds.
    t.strftime('%6N')  # => "323091"                   # Microseconds.
    t.strftime('%9N')  # => "323091400"                # Nanoseconds.
    t.strftime('%12N') # => "323091400000"             # Picoseconds.
    t.strftime('%15N') # => "323091400000000"          # Femptoseconds.
    t.strftime('%18N') # => "323091400000000000"       # Attoseconds.
    t.strftime('%21N') # => "323091400000000000000"    # Zeptoseconds.
    t.strftime('%24N') # => "323091400000000000000000" # Yoctoseconds.
    
  • %s - Number of seconds since the epoch:

    Example
    Time.now.strftime('%s') # => "1656505136"
    

Timezone

  • %z - Timezone as hour and minute offset from UTC:

    Example
    Time.now.strftime('%z') # => "-0500"
    
  • %Z - Timezone name (platform-dependent):

    Example
    Time.now.strftime('%Z') # => "Central Daylight Time"
    

Weekday

  • %A - Full weekday name:

    Example
    Time.now.strftime('%A') # => "Wednesday"
    
  • %a - Abbreviated weekday name:

    Example
    Time.now.strftime('%a') # => "Wed"
    
  • %u - Day of the week, in range (1..7), Monday is 1:

    Example
    t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
    t.strftime('%a')          # => "Sun"
    t.strftime('%u')          # => "7"
    
  • %w - Day of the week, in range (0..6), Sunday is 0:

    Example
    t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
    t.strftime('%a')          # => "Sun"
    t.strftime('%w')          # => "0"
    

Week Number

  • %U - Week number of the year, in range (0..53), zero-padded, where each week begins on a Sunday:

    Example
    t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
    t.strftime('%a')          # => "Sun"
    t.strftime('%U')          # => "26"
    
  • %W - Week number of the year, in range (0..53), zero-padded, where each week begins on a Monday:

    Example
    t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
    t.strftime('%a')          # => "Sun"
    t.strftime('%W')          # => "25"
    

Week Dates

See ISO 8601 week dates.

Example
t0 = Time.new(2023, 1, 1) # => 2023-01-01 00:00:00 -0600
t1 = Time.new(2024, 1, 1) # => 2024-01-01 00:00:00 -0600
  • %G - Week-based year:

    Example
    t0.strftime('%G') # => "2022"
    t1.strftime('%G') # => "2024"
    
  • %g - Week-based year without century, in range (0..99), zero-padded:

    Example
    t0.strftime('%g') # => "22"
    t1.strftime('%g') # => "24"
    
  • %V - Week number of the week-based year, in range (1..53), zero-padded:

    Example
    t0.strftime('%V') # => "52"
    t1.strftime('%V') # => "01"
    

Literals

  • %n - Newline character “\n”:

    Example
    Time.now.strftime('%n') # => "\n"
    
  • %t - Tab character “\t”:

    Example
    Time.now.strftime('%t') # => "\t"
    
  • %% - Percent character ‘%’:

    Example
    Time.now.strftime('%%') # => "%"
    

Shorthand Conversion Specifiers

Each shorthand specifier here is shown with its corresponding longhand specifier.

  • %c - Date and time:

    Example
    Time.now.strftime('%c')             # => "Wed Jun 29 08:01:41 2022"
    Time.now.strftime('%a %b %e %T %Y') # => "Wed Jun 29 08:02:07 2022"
    
  • %D - Date:

    Example
    Time.now.strftime('%D')       # => "06/29/22"
    Time.now.strftime('%m/%d/%y') # => "06/29/22"
    
  • %F - ISO 8601 date:

    Example
    Time.now.strftime('%F')       # => "2022-06-29"
    Time.now.strftime('%Y-%m-%d') # => "2022-06-29"
    
  • %v - VMS date:

    Example
    Time.now.strftime('%v')         # => "29-JUN-2022"
    Time.now.strftime('%e-%^b-%4Y') # => "29-JUN-2022"
    
  • %x - Same as %D.

  • %X - Same as %T.

  • %r - 12-hour time:

    Example
    Time.new(2022, 1, 1, 1).strftime('%r')           # => "01:00:00 AM"
    Time.new(2022, 1, 1, 1).strftime('%I:%M:%S %p')  # => "01:00:00 AM"
    Time.new(2022, 1, 1, 13).strftime('%r')          # => "01:00:00 PM"
    Time.new(2022, 1, 1, 13).strftime('%I:%M:%S %p') # => "01:00:00 PM"
    
  • %R - 24-hour time:

    Example
    Time.new(2022, 1, 1, 1).strftime('%R')     # => "01:00"
    Time.new(2022, 1, 1, 1).strftime('%H:%M')  # => "01:00"
    Time.new(2022, 1, 1, 13).strftime('%R')    # => "13:00"
    Time.new(2022, 1, 1, 13).strftime('%H:%M') # => "13:00"
    
  • %T - 24-hour time:

    Example
    Time.new(2022, 1, 1, 1).strftime('%T')        # => "01:00:00"
    Time.new(2022, 1, 1, 1).strftime('%H:%M:%S')  # => "01:00:00"
    Time.new(2022, 1, 1, 13).strftime('%T')       # => "13:00:00"
    Time.new(2022, 1, 1, 13).strftime('%H:%M:%S') # => "13:00:00"
    
  • %+ (not supported in Time#strftime) - Date and time:

    Example
    DateTime.now.strftime('%+')
    # => "Wed Jun 29 08:31:53 -05:00 2022"
    DateTime.now.strftime('%a %b %e %H:%M:%S %Z %Y')
    # => "Wed Jun 29 08:32:18 -05:00 2022"
    

Flags

Flags may affect certain formatting specifications.

Multiple flags may be given with a single conversion specified; order does not matter.

Padding Flags

  • 0 - Pad with zeroes:

    Example
    Time.new(10).strftime('%0Y') # => "0010"
    
  • _ - Pad with blanks:

    Example
    Time.new(10).strftime('%_Y') # => "  10"
    
  • - - Don’t pad:

    Example
    Time.new(10).strftime('%-Y') # => "10"
    

Casing Flags

  • ^ - Upcase result:

    Example
    Time.new(2022, 1).strftime('%B')  # => "January" # No casing flag.
    Time.new(2022, 1).strftime('%^B') # => "JANUARY"
    
  • # - Swapcase result:

    Example
    Time.now.strftime('%p')  # => "AM"
    Time.now.strftime('%^p') # => "AM"
    Time.now.strftime('%#p') # => "am"
    

Timezone Flags

  • : - Put timezone as colon-separated hours and minutes:

    Example
    Time.now.strftime('%:z')  # => "-05:00"
    
  • :: - Put timezone as colon-separated hours, minutes, and seconds:

    Example
    Time.now.strftime('%::z') # => "-05:00:00"
    

Width Specifiers

The integer width specifier gives a minimum width for the returned string:

Example
Time.new(2002).strftime('%Y')       # => "2002"     # No width specifier.
Time.new(2002).strftime('%10Y')     # => "0000002002"
Time.new(2002, 12).strftime('%B')   # => "December" # No width specifier.
Time.new(2002, 12).strftime('%10B') # => "  December"
Time.new(2002, 12).strftime('%3B')  # => "December" # Ignored if too small.

Specialized Format Strings

Here are a few specialized format strings, each based on an external standard.

HTTP Format

The HTTP date format is based on RFC 2616, and treats dates in the format '%a, %d %b %Y %T GMT':

Example
d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
# Return HTTP-formatted string.
httpdate = d.httpdate    # => "Sat, 03 Feb 2001 00:00:00 GMT"
# Return new date parsed from HTTP-formatted string.
Date.httpdate(httpdate)  # => #<Date: 2001-02-03>
# Return hash parsed from HTTP-formatted string.
Date._httpdate(httpdate)
# => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0}

RFC 3339 Format

The RFC 3339 date format is based on RFC 3339:

Example
d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
# Return 3339-formatted string.
rfc3339 = d.rfc3339      # => "2001-02-03T00:00:00+00:00"
# Return new date parsed from 3339-formatted string.
Date.rfc3339(rfc3339)    # => #<Date: 2001-02-03>
# Return hash parsed from 3339-formatted string.
Date._rfc3339(rfc3339)
# => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0}

RFC 2822 Format

The RFC 2822 date format is based on RFC 2822, and treats dates in the format '%a, %-d %b %Y %T %z']:

Example
d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
# Return 2822-formatted string.
rfc2822 = d.rfc2822      # => "Sat, 3 Feb 2001 00:00:00 +0000"
# Return new date parsed from 2822-formatted string.
Date.rfc2822(rfc2822)    # => #<Date: 2001-02-03>
# Return hash parsed from 2822-formatted string.
Date._rfc2822(rfc2822)
# => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0}

JIS X 0301 Format

The JIS X 0301 format includes the Japanese era name, and treats dates in the format '%Y-%m-%d' with the first letter of the romanized era name prefixed:

Example
d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
# Return 0301-formatted string.
jisx0301 = d.jisx0301    # => "H13.02.03"
# Return new date parsed from 0301-formatted string.
Date.jisx0301(jisx0301)  # => #<Date: 2001-02-03>
# Return hash parsed from 0301-formatted string.
Date._jisx0301(jisx0301) # => {:year=>2001, :mon=>2, :mday=>3}

ISO 8601 Format Specifications

This section shows format specifications that are compatible with ISO 8601. Details for various formats may be seen at the links.

Examples in this section assume:

Example
t = Time.now # => 2022-06-29 16:49:25.465246 -0500

Dates

See ISO 8601 dates.

  • Years:

    • Basic year (YYYY):

      Example
      t.strftime('%Y') # => "2022"
      
    • Expanded year (±YYYYY):

      Example
      t.strftime('+%5Y') # => "+02022"
      t.strftime('-%5Y') # => "-02022"
      
  • Calendar dates:

    • Basic date (YYYYMMDD):

      Example
      t.strftime('%Y%m%d') # => "20220629"
      
    • Extended date (YYYY-MM-DD):

      Example
      t.strftime('%Y-%m-%d') # => "2022-06-29"
      
    • Reduced extended date (YYYY-MM):

      Example
      t.strftime('%Y-%m') # => "2022-06"
      
  • Week dates:

    • Basic date (YYYYWww or YYYYWwwD):

      Example
      t.strftime('%Y%Ww')   # => "202226w"
      t.strftime('%Y%Ww%u') # => "202226w3"
      
    • Extended date (YYYY-Www or <tt>YYYY-Www-D<tt>):

      Example
      t.strftime('%Y-%Ww')    # => "2022-26w"
      t.strftime('%Y-%Ww-%u') # => "2022-26w-3"
      
  • Ordinal dates:

    • Basic date (YYYYDDD):

      Example
      t.strftime('%Y%j') # => "2022180"
      
    • Extended date (YYYY-DDD):

      Example
      t.strftime('%Y-%j') # => "2022-180"
      

Times

See ISO 8601 times.

  • Times:

    • Basic time (Thhmmss.sss, Thhmmss, Thhmm, or Thh):

      Example
      t.strftime('T%H%M%S.%L') # => "T164925.465"
      t.strftime('T%H%M%S')    # => "T164925"
      t.strftime('T%H%M')      # => "T1649"
      t.strftime('T%H')        # => "T16"
      
    • Extended time (Thh:mm:ss.sss, Thh:mm:ss, or Thh:mm):

      Example
      t.strftime('T%H:%M:%S.%L') # => "T16:49:25.465"
      t.strftime('T%H:%M:%S')    # => "T16:49:25"
      t.strftime('T%H:%M')       # => "T16:49"
      
  • Time zone designators:

    • Timezone (time represents a valid time, hh represents a valid 2-digit hour, and mm represents a valid 2-digit minute):

      • Basic timezone (time±hhmm, time±hh, or timeZ):

        Example
        t.strftime('T%H%M%S%z')              # => "T164925-0500"
        t.strftime('T%H%M%S%z').slice(0..-3) # => "T164925-05"
        t.strftime('T%H%M%SZ')               # => "T164925Z"
        
      • Extended timezone (time±hh:mm):

        Example
        t.strftime('T%H:%M:%S%z') # => "T16:49:25-0500"
        
    • See also:

Combined Date and Time

See ISO 8601 Combined date and time representations.

An ISO 8601 combined date and time representation may be any ISO 8601 date and any ISO 8601 time, separated by the letter T.

For the relevant strftime formats, see Dates and Times above.

From doc/language/strftime_formatting.rdoc in Ruby 4.0. View on GitHub ↗ docs.ruby-lang.org ↗