Date – How to Force Date to Read Day/Month/Year

date

How to I get the GNU date command to interpret dates in the format 'dd/mm/yyyy', for example:

What I get:

$ date  -d '09/07/2016'
Wed, Sep  7, 2016 12:00:00 AM

What I want:

$ date  -d '09/07/2016'
Sat, Jul  9, 2016 12:00:00 AM

I've tried setting LC_ALL but to no avail.

Best Answer

Note that date -d is a GNU extension. The syntax it expects is fixed and independent from the locale. In particular, it does not use POSIX getdate() to parse the date (even though the interface GNU date uses used to be called getdate() as well).

Some builds of some versions of busybox also recognise a -d option, but the range of supported formats is narrower. In particular, it does not recognise mm/dd/YYYY. You can however pass a -D <strptime-format> option (thanks @BinaryZebra) to specify the format you like:

$ date -D %d/%m/%Y -d 01/10/2016
Sat Oct  1 00:00:00 BST 2016

AT&T (ast-open) date, since 1995, also supports a GNU-style -d option. That one does use POSIX getdate(). So with that date implementation, you can use the DATEMSK variable to change the way dates are parsed and since 1996, you can use the -p option to pass a strptime-style parsing format on the command line:

$ date --version
  version         date (AT&T Research) 2011-01-27
$ date -d 01/10/2016
Sun Jan 10 13:36:39 GMT 2016
$ date -d 01/10/2016 -p %d/%m/%Y
Sat Oct  1 13:36:51 BST 2016

AT&T ksh93's printf %T also uses a getdate()-compatible API and so can also be affected by the DATEMSK variable, so in ksh93, you can do:

$ DATEMSK=/dev/stdin <<< %d/%m/%Y printf '%T\n' 01/10/2016
Sat Oct  1 13:47:06 BST 2016

To parse a date portably in a zsh script, you can used the strftime builtin (after loading it) with the -r option:

$ zmodload zsh/datetime
$ strftime -s REPLY -r '%d/%m/%Y' 09/07/2016
$ strftime %c $REPLY
Sat 09 Jul 2016 00:00:00 BST

zsh's strftime -r uses POSIX strptime() to parse the string. As such, it is locale-dependant. In a French locale for instance, you can use strftime -r %d-%b-%Y 14-juillet-2016 to parse a French date.

Some strptime() implementations like GNU's still accept the English month/day names when in non-English locales, but not all (Solaris 11's one doesn't for instance). Something to bear in mind when parsing an English date in the user's locale.

Recent versions of bash also have a ksh-style printf '%(format)T', but that one has no time parsing capability.

For completeness, on BSDs, date accepts a -f <strptime-format> which you can use in combination with -j to reformat a date:

$ date -jf %d/%m/%Y 01/10/2016
Sat Oct  1 13:47:06 BST 2016
Related Question