![](/style/images/good.png)
![](/style/images/bad.png)
Idiosyncratic Ruby: What the Time?
source link: https://idiosyncratic-ruby.com/57-what-the-time.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
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
- 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
- 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
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
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)
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
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
- 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
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK