%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
- Month
- Day of Month
- Year without Century
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
- Year
- Month
- Day of Month
Time.utc(2016, 5, 24).strftime("%F") # => "2016-05-24"
%v | Date, VMS
With Time#strftime
%_d-%^b-%Y
- Space Padded Day of Month
- Uppercased Month Name
- Year
Time.utc(2016, 5, 24).strftime("%v") # => "24-MAY-2016"
With Date#strftime and DateTime#strftime
%_d-%b-%Y
- Space Padded Day of Month
- Month Name
- Year
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
- Hour (24h)
- Minute
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
- Hour (12h)
- Minute
- Second
- Daytime
Time.utc(2016, 5, 24, 15, 29, 59).strftime("%r") # => "03:29:59 PM"
%T, %X | Time, Hour + Minute + Second
%H:%M:%S
- Hour (24h)
- Minute
- Second
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
- Weekday (Short)
- Month (Short)
- Day of Month
- Time (24h)
- Year
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
- Weekday (Short)
- Month (Short)
- Day of Month
- Time (24h)
- Numerical Time Zone Offset
- Year
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
- Sign
- Two-digit Hour
- Two-digit Minute
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
- Please Comment on GitHub
- Next Article: Magic Instructions
- Previous Article: US-ASCII-8BIT