Print the current date in a customized format
If you use the command line interpreter on GNU/Linux, you might already know
the numerous date and time formats the GNU command
date
can apply to print its information. The manual page
date(1)
references all the formats that can be specified using combinable sequences in
an argument beginning with +
.
Here is an example printing the current date and time in a provided format:
~$ date +"On %A, %-d %B %Y, at %R (day %j of the year)".
On Friday, 14 April 2023, at 17:20 (day 104 of the year).
For some sequences (like %A
and %B
above), date
will use the localisation
specified using the environment variable LC_TIME
to print values in the
designated language. This variable can be set to any localisation available on
the system, which can be listed using the commande locale -a
. If the
specified locale does not exist, date
will fall back to the english language.
On a system configured to use a specific localisation, a different localisation
can occasionally be used by setting the environment variable LC_TIME
for the
command like so : LC_TIME=C date +%B
(the localisation C
represents the
system defaults values, so here the english language will be used).
Printing a specific date
A lesser known functionality of date
makes it a much more interesting command
than expected. It is only discreetly mentioned in its manual
page and can
easily be overlooked: it is about the option -d
that allows specifying a date
to print, and especially specifying a date relatively to another date.
Printing a absolute date
This date or time can be specified in an absolute way, like 1914-07-28 06:00
or 28 July 1914 17:00
(only english names are recognised):
~$ date -d '1914-07-28 06:00'
Tue Jul 28 06:00:00 AST 1914
~$ date -d '28 July 1914 06:00:00'
Tue Jul 28 06:00:00 AST 1914
Printing a relative date
Yet what is particularly convenient is specirying an input date relatively to the current date and time or to a provided date and time. For example:
$ date -d 'yesterday'
Fri Oct 3 18:15:37 CEST 2014
$ date -d '2 days ago'
Thu Oct 2 18:15:42 CEST 2014
$ date -d 'last monday'
Mon 29 Sep 00:00:00 CEST 2014
$ date -d '1918-11-11 - 4 years'
mercredi 11 novembre 1914, 00:00:00 (UTC+0200)
Wed Nov 11 00:00:00 CEST 1914
$ date -d '2000-01-01 - 1 day'
Fri Dec 31 00:00:00 CEST 1999
Date input formats are referenced in the info page of date
: run the command
info date
and follow the link Date input formats::
(place the cursor on it
and press Enter). This page provides links to references of all accepted
formats to specify the date to print; for information on relative dates,
follow the link Relative items in date strings::
from this page.
Subtleties of the expression “last month
”
Be careful about some subtleties in the use of relative dates: as mentioned in
the documentation, the term last month
really represents - 30 days
. Be
watchful when using it with the last day of a month as reference:
~$ date -d "2014-10-31 last month"
Wed Oct 1 00:00:00 CEST 2014
To get the name of the last month, it is best to use a less problematic day of
the month, for example the 15th. This can be achieved by using two nested calls
to date
: the first will construct the date of the 15th of the current month
and the second the name of the last month:
$ date -d "$(date "+%Y-%m-15") last month" +%B
September
Specifying a time zone for dates in input or output
Time zone for the date to be printed
As a complement, note that, like many commands, to obtain the time from another
time zone, you can simply set the environment variable TZ
before calling
date
.
Thus, to know the current time in Singapore, you could use the following command:
$ TZ="Asia/Singapore" date
Sun Oct 15 00:37:00 +08 2014
Files providing information about time zones corresponding to cities and
localities specified by TZ
are stored in the directory
/usr/share/zoneinfo
(at least on Debian). To get an idea of all available
city files, use the command:
find /usr/share/zoneinfo -printf "%P\n"
To get the time for the zone UTC-8 or GMT-8 (it seems that, in this case, GMT is a substitute for UTC), you also could use:
~$ TZ="Etc/GMT-8" date +"%A, %-d %B %Y, %T %z"
Sunday, 5 October 2014, 00:37:00 +0800
This is not an error, you indeed have to specify the file Etc/GMT-8
to get
the time zone for GMT+8
. This is a confusing notation inherited from the
POSIX standard. Debian incidentally has the bug
#540305 on this
topic (open since 2009…).
Time zone for the input date
It is also possible to specify the time zone for the date we specify as input
using the option -d
.
For example, we will seek to know what was the time in Hong-Kong when it was 18:45 on the 4 October 2014 in Port-au-Prince (in Haïti):
- if we know that Port-au-Prince used the time zone UTC-4 on october 2014 (as
summer time), we can add the time zone specifier
-0400
in the input date:~$ TZ="Asia/Hong_Kong" date -d '2014-10-04 18:45-0400' Sun Oct 5 06:45:00 HKT 2014
- but if we don't know that time zone was in use in Port-au-Prince on this day,
we can specify the place using the variable
TZ
here as well in the argument for the option-d
:~$ TZ="Asia/Hong_Kong" date -d 'TZ="America/Port-au-Prince" 2014-10-04 18:45' Sun Oct 5 06:45:00 HKT 2014