Why won’t `date` accept it’s own default output?

Posted on

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

Leave a Reply

Your email address will not be published. Required fields are marked *