Problem :
On my system right now by default date
outputs:
$ date
Fri 29 Jan 22:04:26 GMT 2016
However if I try to feed dates of this format back into date
it results in “invalid date”:
$ date -d "$(date)"
date: invalid date ‘Fri 29 Jan 22:06:14 GMT 2016’
I realise that I can manually choose a format that date
will understand:
$ date -d "@$(date +%s)"
Fri 29 Jan 22:08:03 GMT 2016
But I am interested in why it is outputting a format that it won’t accept back in.
Solution :
I just spent about two hours searching for this answer which has bugged me for years and I finally found it!!
By default date
outputs a date in the current locale format such as en_GB.UTF-8
or en_AU.UTF-8
or de_DE.UTF-8
etc
Your default locale looks like it is similar to mine and displays dates in the format:
date_fmt "%a %e %b %H:%M:%S %Z %Y"
Unfortunately this is one of the few formats the date command can’t understand. However, if CAN understand a very similar format
date_fmt "%a %e %b %Y %H:%M:%S %Z"
“Fri 29 Jan 2016 22:04:26 GMT” Works
“Fri 29 Jan 22:04:26 GMT 2016” Doesn’t
Why the very commonly used locale’s en_GB.UTF-8 and en_AU.UTF-8 use a format that date
can’t read I don’t know but it’s very easy to tweak it so that it won’t bother you again, at least not until you reinstall your system or your definitions get overwritten by an overzealous update >:-(
How to customize your locale’s date format in three steps
I found the following information here:
1. Check which locale you’re using
First check which locale your system is using for it’s time and date format
$ locale
LANG=en_AU.UTF-8
LANGUAGE=en_AU
LC_CTYPE="en_AU.UTF-8"
LC_NUMERIC=en_AU.UTF-8
LC_TIME=en_AU.UTF-8
LC_COLLATE="en_AU.UTF-8"
LC_MONETARY=en_AU.UTF-8
LC_MESSAGES="en_AU.UTF-8"
LC_PAPER=en_AU.UTF-8
LC_NAME=en_AU.UTF-8
LC_ADDRESS=en_AU.UTF-8
LC_TELEPHONE=en_AU.UTF-8
LC_MEASUREMENT=en_AU.UTF-8
LC_IDENTIFICATION=en_AU.UTF-8
LC_ALL=
Note the LC_TIME= entry. Mine is English Australian: en_AU.UTF-8 your’s might be en_GB_UTF-8
2. Edit the locale definition
Open a terminal and edit the appropriate locale definition
$ sudo nano /usr/share/i18n/locales/{LC_Time}
e.g.
$ sudo nano /usr/share/i18n/locales/en_AU
Scroll down to the LC_TIME section, here’s mine:
LC_TIME
abday "Sun";"Mon";"Tue";"Wed";"Thu";"Fri";"Sat"
day "Sunday";/
"Monday";/
"Tuesday";/
"Wednesday";/
"Thursday";/
"Friday";/
"Saturday"
abmon "Jan";"Feb";/
"Mar";"Apr";/
"May";"Jun";/
"Jul";"Aug";/
"Sep";"Oct";/
"Nov";"Dec"
mon "January";/
"February";/
"March";/
"April";/
"May";/
"June";/
"July";/
"August";/
"September";/
"October";/
"November";/
"December"
d_t_fmt "%a %d %b %Y %T %Z"
d_fmt "%d//%m//%y"
t_fmt "%T"
am_pm "AM";"PM"
t_fmt_ampm "%I:%M:%S %p"
date_fmt "%a %e %b %Y %H:%M:%S %Z"
week 7;19971130;1
END LC_TIME
All you need to change is the date_fmt
entry
I changed mine from:
date_fmt "%a %e %b %H:%M:%S %Z %Y"
to date_fmt "%a %e %b %Y %H:%M:%S %Z"
Save the file and exit the editor
3 Regenerate your locale
You recompile your locale definition files with:
$ sudo locale-gen
That’s it! Now the date
command should default to giving you output in a format that it can itself accept natively back as input
$ date -d "$(date)"
Mon 17 Aug 2020 17:58:37 AWST