What the Time?

%a %A %b %B %c %C %d %D %e %F %g %G %h %H %I %j %k %l %L %m %M %n %N %p %P %Q %r %R %s %S %t %T %u %U %v %V %w %W %x %X %y %Y %z %Z %+ %% - _ 0 ^ # :

Date and time formatting is traditionally done with strftime. Not any different in Ruby, which includes a public domain based strftime implementation accessible via Time#strftime. Ruby would not be Ruby if it would not add some confusion: There is a second implementation included in the standard library which is used by Date#strftime and DateTime#strftime. It behaves similarly in most cases, but also differs in some nuances (for example, additional formatting directives like %Q are supported).

Usage

strftime() is called on time objects to convert them to strings:

Time.utc(2016, 05, 24, 15).strftime("%a %b %e %T %Y")
# => "Tue May 24 15:00:00 2016"

Similar to format strings or String.unpack() you have to pass a template string which contains formatting directives (like %Y for year). Many of the directives are combined directives (like %T for time), constructed from multiple base directives ("atoms"). The following tables give an overview, scroll further down for an explanation of every directive.

Atoms

Point of Time Atoms (Example)
Year %Y (2016)
%C (20)
%y (16)
Month %m (05)
Day %d (31)
%j (365)
Hour/Daytime %H (23)
%I (11)
%P (am)
Minute %M (59)
Second %S (59)
Fraction %N (479254327)

English

Name Atoms (Example)
English Month Name %B (January)
%b (Jan)
English Weekday Name %A (Monday)
%a (Mon)

Week Based

Point of Time Atoms (Example)
Year (by Week) %G (2016)
%g (16)
Week %W (52)
%U (52)
%V (52)
Weekday %u (3)
%w (3)

Other

Name Atoms (Example)
Time Zone %z (+0000)
%Z (UTC)
Unix Timestamp %s (1464188400)
Unix Timestamp (Milliseconds)¹ %Q (1464188400)

¹ Only available in Date/DateTime's strftime() implementation

Formatting Flags and Padding

Time formatting directives support some basic padding and formatting options via flags that appear between % and the directive type. Padding is the minimum length of the output, if the value is smaller, the remaining space will be filled with spaces or zeros.

Flag Description
- Do not apply default padding
_ Use spaces for padding
0 Use zeros for padding
^ Upcase
# Swap case

Examples:

time = Time.utc(2016, 05, 25, 15) #=> 2016-05-25 15:00:00 UTC

time.strftime("%P") # => "pm"
time.strftime("%^P") # => "PM"
time.strftime("%#P") # => "PM"
time.strftime("%10P") # =>  "        pm"
time.strftime("%010P") # => "00000000pm"
time.strftime("%_10P") # =>  "        pm"

time.strftime("%m") # => "05"
time.strftime("%-m") # => "5"
time.strftime("%10m") #=> "0000000005"
time.strftime("%010m") #=> "0000000005"
time.strftime("%_10m") #=> "         5"

Combined Directives and Aliases

Directive Alias/From Atoms
%c %a %b %e %T %Y
%D %m/%d/%y
%e %_d
%F %Y-%m-%d
%h %b
%k %_H
%l %_I
%L %3N
%n "\n"
%p %^P
%r %I:%M:%S %p
%R %H:%M
%t "\t"
%T %H:%M:%S
%v Time#strftime: %e-%^b-%4Y
Date#strftime: %e-%b-%4Y
%x %m/%d/%y
%X %H:%M:%S
%+¹ %a %b %e %H:%M:%S %Z %Y

¹ Only available in Date/DateTime's strftime() implementation

Years Directives

%Y | Year, with Century

Will display the time's year with a default padding of 4:

Time.utc(2016).strftime("%Y") # => "2016"
Time.utc(20000).strftime("%Y") # => "20000"
Time.utc(2).strftime("%Y") # => "0002"
Time.utc(2).strftime("%-Y") # => "2"

%y | Year, without Century

Will display the time's year modulo 100 with a default padding of 2:

Time.utc(2016).strftime("%y") # => "16"
Time.utc(20000).strftime("%y") # => "00"
Time.utc(2).strftime("%y") # => "02"
Time.utc(2).strftime("%-y") # => "2"

%C | Century

Will display the time's year divided by 100 with a default padding of 2:

Time.utc(2016).strftime("%C") # => "20"
Time.utc(20000).strftime("%C") # => "000"
Time.utc(2).strftime("%C") # => "00"
Time.utc(2).strftime("%-C") # => "0"

%G | Year (Week based), with Century

Returns the year based on which year the time's week belongs to:

Time.utc(2014, 12, 29).strftime("%G") # => "2015"
Time.utc(2017, 1, 1).strftime("%G") #=> "2016"

%g | Year (Week based), without Century

Returns the year based on which year the time's week belongs to:

Time.utc(2014, 12, 29).strftime("%g") # => "15"
Time.utc(2017, 1, 1).strftime("%g") #=> "16"

Months Directives

%m | Month as Number

Number of month, with a default padding of 2:

Time.utc(2016, 5).strftime("%m") # => "05"
Time.utc(2016, 5).strftime("%-m") # => "5"

%B | Month Name

Locale-independent (English) month name:

Time.utc(2016, 1).strftime("%B") # => "January"

%b, %h | Month Name (Abbreviated)

Locale-independent (English) three-letter month name:

Time.utc(2016, 1).strftime("%b") # => "Jan"
Time.utc(2016, 1).strftime("%h") # => "Jan"

Weeks Directives

See ISO 8601 for an explanation of week number construction.

%U | Week Number (Sunday Starts Week) | 00..53

Considers Sunday the first day of the week. Will return 00 if week belongs to last year:

Time.utc(2015, 1, 1).strftime("%U") # => "00" # Thursday
Time.utc(2016, 1, 1).strftime("%U") # => "00" # Friday
Time.utc(2017, 1, 1).strftime("%U") # => "01" # Sunday

%V | Week Number (Week Based Year) | 01..53

Considers Sunday the first day of the week. Will return last years week number if week belongs to last year:

Time.utc(2015, 1, 1).strftime("%V") # => "01" # Thursday
Time.utc(2016, 1, 1).strftime("%V") # => "53" # Friday
Time.utc(2017, 1, 1).strftime("%V") # => "52" # Sunday

%W | Week Number (Monday Starts Weeks) | 00..53

Considers Sunday the last day of the week. Will return 00 if week belongs to last year:

Time.utc(2015, 1, 1).strftime("%W") # => "00" # Thursday
Time.utc(2016, 1, 1).strftime("%W") # => "00" # Friday
Time.utc(2017, 1, 1).strftime("%W") # => "00" # Sunday

Days Directives

%j | Day of Year | 001..366

Which day of the year with a default padding of 3:

Time.utc(2016, 5, 24).strftime("%j") # => "145"
Time.utc(2016, 1, 1).strftime("%j") # => "001"
Time.utc(2016, 1, 1).strftime("%-j") # => "1"

%d | Day of Month | 01..31

Which day of the month with a default (zero) padding of 2:

Time.utc(2016, 5, 24).strftime("%d") # => "24"
Time.utc(2016, 1, 1).strftime("%d") # => "01"
Time.utc(2016, 1, 1).strftime("%-d") # => "1"

%e | Day of Month (Space Padded) | 01..31

Which day of the month with a default (space) padding of 2:

Time.utc(2016, 5, 24).strftime("%e") # => "24"
Time.utc(2016, 1, 1).strftime("%e") # => " 1"
Time.utc(2016, 1, 1).strftime("%-e") # => "1"

%u | Weekday as Number (Monday Starts Week) | 1..7

Number of day in the week, value of Sunday is 7:

Time.utc(2016, 5, 22).strftime("%u") # => 7 # Sunday
Time.utc(2016, 5, 23).strftime("%u") # => 1 # Monday
Time.utc(2016, 5, 24).strftime("%u") # => 2 # Tuesday
Time.utc(2016, 5, 25).strftime("%u") # => 3 # Wednesday
Time.utc(2016, 5, 26).strftime("%u") # => 4 # Thursday
Time.utc(2016, 5, 27).strftime("%u") # => 5 # Friday
Time.utc(2016, 5, 28).strftime("%u") # => 6 # Saturday

%w | Weekday as Number (Sunday Starts Week) | 0..6

Number of day in the week, value of Sunday is 0:

Time.utc(2016, 5, 22).strftime("%u") # => 0 # Sunday
Time.utc(2016, 5, 23).strftime("%u") # => 1 # Monday
Time.utc(2016, 5, 24).strftime("%u") # => 2 # Tuesday
Time.utc(2016, 5, 25).strftime("%u") # => 3 # Wednesday
Time.utc(2016, 5, 26).strftime("%u") # => 4 # Thursday
Time.utc(2016, 5, 27).strftime("%u") # => 5 # Friday
Time.utc(2016, 5, 28).strftime("%u") # => 6 # Saturday

%A | Weekday Name

Locale-independent (English) name of weekday:

Time.utc(2016, 5, 22).strftime("%A") # => "Sunday"
Time.utc(2016, 5, 23).strftime("%A") # => "Monday"
Time.utc(2016, 5, 24).strftime("%A") # => "Tuesday"
Time.utc(2016, 5, 25).strftime("%A") # => "Wednesday"
Time.utc(2016, 5, 26).strftime("%A") # => "Thursday"
Time.utc(2016, 5, 27).strftime("%A") # => "Friday"
Time.utc(2016, 5, 28).strftime("%A") # => "Saturday"

%a | Weekday Name (Abbreviated)

Locale-independent (English) three-letter name of weekday:

Time.utc(2016, 5, 22).strftime("%a") # => "Sun"
Time.utc(2016, 5, 23).strftime("%a") # => "Mon"
Time.utc(2016, 5, 24).strftime("%a") # => "Tue"
Time.utc(2016, 5, 25).strftime("%a") # => "Wed"
Time.utc(2016, 5, 26).strftime("%a") # => "Thu"
Time.utc(2016, 5, 27).strftime("%a") # => "Fri"
Time.utc(2016, 5, 28).strftime("%a") # => "Sat"

%D, %x | Date, American

%m/%d/%y

Time.utc(2016, 5, 24).strftime("%D") # => "05/24/16"
Time.utc(2016, 5, 24).strftime("%x") # => "05/24/16"

%F | Date, ISO 8601

%Y-%m-%d

Time.utc(2016, 5, 24).strftime("%F") # => "2016-05-24"

%v | Date, VMS

With Time#strftime

%_d-%^b-%Y

Time.utc(2016, 5, 24).strftime("%v") # => "24-MAY-2016"

With Date#strftime and DateTime#strftime

%_d-%b-%Y

require "date"
Time.utc(2016, 5, 24).to_date.strftime("%v") # => "24-May-2016"

Daytime Directives

%P | Meridian Indicator (Lowercase)

Returns "am" for hours between 0 and 11, returns "pm" for hours between 12 and 23:

Time.utc(2016, 5, 24, 15).strftime("%P") # => "pm"
Time.utc(2016, 5, 24, 3).strftime("%P") # => "am"

%p | Meridian Indicator (Uppercase)

Returns "AM" for hours between 0 and 11, returns "PM" for hours between 12 and 23:

Time.utc(2016, 5, 24, 15).strftime("%p") # => "PM"
Time.utc(2016, 5, 24, 3).strftime("%p") # => "AM"

Hours Directives

%H | Hour of Day, 24h (Zero Padded) | 0..23

Time's hour on the 24h clock:

Time.utc(2016, 5, 24, 15).strftime("%H") # => "15"
Time.utc(2016, 5, 24, 3).strftime("%H") # => "03"
Time.utc(2016, 5, 24, 3).strftime("%-H") # => "3"

%k | Hour of Day, 24h (Space Padded) | 0..23

Time's hour on the 24h clock:

Time.utc(2016, 5, 24, 15).strftime("%k") # => "15"
Time.utc(2016, 5, 24, 3).strftime("%k") # => " 3"
Time.utc(2016, 5, 24, 3).strftime("%-k") # => "3"

%I | Hour of Day, 12h (Zero Padded) | 0..11

Time's hour on the 12h clock:

Time.utc(2016, 5, 24, 15).strftime("%I") # => "03"
Time.utc(2016, 5, 24, 3).strftime("%I") # => "03"
Time.utc(2016, 5, 24, 3).strftime("%-I") # => "3"

%l | Hour of Day, 12h (Space Padded) | 0..11

Time's hour on the 12h clock:

Time.utc(2016, 5, 24, 15).strftime("%l") # => " 3"
Time.utc(2016, 5, 24, 3).strftime("%l") # => " 3"
Time.utc(2016, 5, 24, 3).strftime("%-l") # => "3"

Minutes Directives

%M | Minute of Hour | 00..59

Time's minutes with default padding of 2:

Time.utc(2016, 5, 24, 15, 29).strftime("%M") # => "29"
Time.utc(2016, 5, 24, 15, 1).strftime("%M") # => "01"
Time.utc(2016, 5, 24, 15, 1).strftime("%-M") # => "1"

%R | Time, Hour + Minute

%H:%M

Time.utc(2016, 5, 24, 15, 29).strftime("%R") # => "15:29"

Seconds Directives

%S | Second of Minute | 00..60

Time's seconds with default padding of 2:

Time.utc(2016, 5, 24, 15, 29, 59).strftime("%S") # => "59"
Time.utc(2016, 5, 24, 15, 29, 1).strftime("%S") # => "01"
Time.utc(2016, 5, 24, 15, 29, 1).strftime("%-S") # => "1"

%s | Seconds Since Unix Epoch

Number of seconds since 1970-01-01 00:00:00 UTC. This known as Unix timestamps. It returns the same value (as string) like Time#to_i:

Time.utc(2016, 5, 24, 15, 29, 59).strftime("%s") # => "1464103799"
Time.utc(2016, 5, 24, 15, 29, 59).to_i # => 1464103799

%r | Time, Hour + Minute + Second + Daytime

%I:%M:%S %p

Time.utc(2016, 5, 24, 15, 29, 59).strftime("%r") # => "03:29:59 PM"

%T, %X | Time, Hour + Minute + Second

%H:%M:%S

Time.utc(2016, 5, 24, 15, 29, 59).strftime("%T") # => "15:29:59"
Time.utc(2016, 5, 24, 15, 29, 59).strftime("%X") # => "15:29:59"

%c | Date, Weekday + Month + Day of Month + Time + Year

%a %b %e %T %Y

Time.utc(2016, 5, 24, 15, 29, 59).strftime("%c") # => "Tue May 24 15:29:59 2016"

%+ | Date, date(1) Style

Only available in Date/DateTime's strftime() implementation

%a %b %e %T %Z %Y

require "date"
Time.utc(2016, 5, 24, 15, 29, 59).to_datetime.strftime("%+")
# => "Tue May 24 15:29:59 +00:00 2016"

Smaller Than Seconds Directives

%L | Millisecond | 000..999

Millisecond with default padding of 3. More precise fractions will be truncated:

Time.utc(2016, 5, 24, 15, 29, 0.1239).strftime("%L") # => "123"

%N | Fraction, Default: Nanosecond

Specifies time fractions like milliseconds (precision of 3), microseconds (precision of 6), or nanoseconds (precision of 9). More precise fractions will be truncated. Cannot be combined with padding:

Time.utc(2016, 5, 24, 15, 29, 0.1234567890).strftime("%3N") # => "123"
Time.utc(2016, 5, 24, 15, 29, 0.1234567890).strftime("%6N") # => "123456"
Time.utc(2016, 5, 24, 15, 29, 0.1234567890).strftime("%9N") # => "123456789"
Time.utc(2016, 5, 24, 15, 29, 0.1234567890).strftime("%N") # => "123456789"

%Q | Milliseconds Since Unix Epoch

Only available in Date/DateTime's strftime() implementation

Number of milliseconds since 1970-01-01 00:00:00 UTC:

require "date"
Time.utc(2016, 5, 24, 15, 29, 59.012).to_datetime.strftime("%Q") #=> "1464103799012"

Time Zone Directives

%z | Time Zone, Offset from UTC

A numerical time zone identifier in the format of

which describes the offset from UTC:

Time.utc(2016, 5, 24).strftime("%z") # => "+0000"
Time.local(2016, 5, 24).strftime("%z") # => "+0200"

The output separates hours and minutes when using a single : flag:

Time.local(2016, 5, 24).strftime("%:z") # => "+02:00"

It will also show the seconds offset when using two :: colons:

Time.local(2016, 5, 24).strftime("%::z") # => "+02:00:00"

When using :::, it will only return significant information (no zero minutes or seconds):

Time.local(2016, 5, 24).strftime("%:::z") # => "+02"

%Z | Time Zone, Abbreviated, OS Dependent

With Time#strftime

Big %Z displays a platform dependent time zone string:

Time.utc(2016, 5, 24).strftime("%Z") # => "UTC"
Time.local(2016, 5, 24).strftime("%Z") # => "CEST"

Ruby's documentation disencourages %Z, because it has a different result on different platforms and also does not properly identify the time zone:

While all directives are locale independent since Ruby 1.9, %Z is platform dependent. So, the result may differ even if the same format string is used in other systems such as C.

%z is recommended over %Z. %Z doesn’t identify the timezone. For example, "CST" is used at America/Chicago (-06:00), America/Havana (-05:00), Asia/Harbin (+08:00), Australia/Darwin (+09:30) and Australia/Adelaide (+10:30). Also, %Z is highly dependent on the operating system. For example, it may generate a non ASCII string on Japanese Windows. i.e. the result can be different to "JST". So the numeric time zone offset, %z, is recommended.

With Date#strftime and DateTime#strftime

Date's strftime() implementation outputs a numerical offset, similar to %:z:

require "date"
Time.utc(2016, 5, 24).to_datetime.strftime("%Z") # => "+00:00"
Time.local(2016, 5, 24).to_datetime.strftime("%Z") # => "+02:00"

Non Interpolating Directives

%n | Newline

Output a newline:

Time.utc(2016).strftime("%n") # => "\n"

%t | Tab

Output a tab:

Time.utc(2016).strftime("%t") # => "\t"

%% | %

A single % needs to be escaped:

Time.utc(2016).strftime("%%") # => "%"

Resources

Also See

More Idiosyncratic Ruby