Date validation in shell

I want to validate the below date format in shell script


I’m using date -d "2015-Jul-13" +"%Y-%b-%d" but its giving error as

date: invalid date '2015-Jul-13'

GNU date does not support YYYY-MMM-DD. However, it does understand DD-MMM-YYYY. So if you really have to handle dates of this format you can do it with something like this, which simply swaps the arguments around to a format that date expects:


dmy=$(echo "$ymd" | awk -F- '{ OFS=FS; print $3,$2,$1 }')
if date --date "$dmy" >/dev/null 2>&1
    echo OK

Here’s an all shell solution. Breaking it down, the IFS=- instructions tells the shell to split a forthcoming command line by hyphen - instead of whitespace. The set $ymd parses the $ymd variable as for a command line, but now splits by hyphen, assigning values to the parameters $1, $2 et seq. The echo "$3-$2-$1" trivially outputs the three captured values in reversed order.


dmy=$(IFS=-; set $ymd; echo "$3-$2-$1")
if date --date "$dmy" >/dev/null 2>&1
    echo OK
Answered By: roaima

From manpage:-

       The --date=STRING is a mostly free format human readable date string such as "Sun, 29 Feb 2004 16:21:42 -0800"
       or  "2004-02-29  16:21:42" or even "next Thursday".  A date string may contain items indicating calendar date,
       time of day, time zone, day of week, relative time, relative date, and numbers.  An empty string indicates the
       beginning  of  the  day.   The  date string format is more complex than is easily documented here but is fully
       described in the info documentation.

But it seems not recognize YYYY-MMM-DD format. So, you can use either from below or similar like:

$ date -d "2015-07-13" +"%Y-%b-%d"
$ date -d "Jul 13 2015" +"%Y-%b-%d"
$ date -d "13 Jul 2015" +"%Y-%b-%d"

OR you’ve to convert/re-formate it before sending to date!

Also see How do you specify a format for the input to date?

I recommend to Visit: Date input formats.

Here are the rules.

For numeric months, the ISO 8601 format ‘year-month-day’ is allowed, where year is any positive number, month is a number between 01 and 12, and day is a number between 01 and 31. A leading zero must be present if a number is less than ten. If year is 68 or smaller, then 2000 is added to it; otherwise, if year is less than 100, then 1900 is added to it. The construct ‘month/day/year’, popular in the United States, is accepted. Also ‘month/day’, omitting the year.

Literal months may be spelled out in full: ‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’ or ‘December’. Literal months may be abbreviated to their first three letters, possibly followed by an abbreviating dot. It is also permitted to write ‘Sept’ instead of ‘September’.

When months are written literally, the calendar date may be given as any of the following:

 day month year
 day month
 month day year

emphasized by me

Here you can see that there is no format like year-month-day! (for months are written literally)

Answered By: Pandya

With zsh you could use the strftime builtin (available via zsh/datetime) with -r (reverse):

strftime -r format timestring

which uses format to parse the timestring and output the number of seconds since epoch:

zmodload zsh/datetime
strftime -r %Y-%b-%d 2015-Jul-13

This errors out if the date is invalid:

strftime -r %Y-%b-%d 2015-Jul-33
zsh:strftime:5: format not matched

You can also convert the seconds since epoch to any other standard/custom date format e.g.

strftime '%A, %B %d, %Y' 1447970400
Friday, November 20, 2015
Answered By: don_crissti
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.