1. Overview

When working with dates in Linux, it’s common to need to validate that a date argument is in the “yyyy-mm-dd” format. This format is widely used in Linux systems and is a standard format for many applications.

In this tutorial, we’ll explore how to check whether a date argument is in the “yyyy-mm-dd” format in different ways.

2. Checking the Variable’s Format Using Regex

When we talk about if a variable’s value is in a certain format, we want to check if the value matches a specific pattern. This is precisely what Regex is good at.

Therefore, let’s first look at how to solve the problem using Regex.

Bash’s if statement supports the =~ operator to apply Regex-based pattern match checking. Therefore, let’s create a simple shell script to check if user input is in the desired date format:

$ cat check_date.sh
#!/bin/bash
INPUT_DT="$1"

if [[ $INPUT_DT =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
    echo "The input $INPUT_DT is in the yyyy-mm-dd date format."
else
    echo "The input is NOT in the yyyy-mm-dd date format."
fi

As the cat‘s output above shows, our check_date.sh script has an if-else block to check the input’s format. Then, it prints the corresponding information depending on the check result.

The Regex “*^[0-9]{4}-[0-9]{2}-[0-9]{2}$*” is pretty straightforward. But it’s worth mentioning that we shouldn’t wrap the Regex in quotes, or the =~ check fails.

Next, let’s test if our script works for different inputs:

$ ./check_date.sh 1992-08-08
The input 1992-08-08 is in the yyyy-mm-dd date format.

$ ./check_date.sh 08.08.1992
The input 08.08.1992 is NOT in the yyyy-mm-dd date format.

$ ./check_date.sh 1992-AUG-08
The input 1992-AUG-08 is NOT in the yyyy-mm-dd date format

As we can see in the tests above, our script can correctly tell if our inputs are in the “yyyy-mm-dd” date format or not.

Notably, although an argument passes the Regex-base check, it doesn’t mean it’s a valid date value. An example can explain it quickly:

$ ./check_date.sh 1992-42-42
The input 1992-42-42 is in the yyyy-mm-dd date format.

As we’ve seen, the value “1992-42-42” passes the check_date.sh script’s check. However, it’s not a valid date.

3. Validating the Date Variable

We’ve learned that checking the date format using Regex doesn’t guarantee the value is a valid date. So now, let’s see how to validate a date value.

3.1. Using the date Command

We can parse a static string value using the date command with the -d option. Of course, we need to tell date which date format it should parse the string:

$ cat validate_date.sh
#!/bin/bash

INPUT_DT="$1"

if date -d "$INPUT_DT" "+%Y-%m-%d" >/dev/null 2>&1; then
    echo "The input $INPUT_DT is a valid date string in the yyyy-mm-dd format."
else
    echo "The input $INPUT_DT is NOT a valid date string in the yyyy-mm-dd format."
fi

The if statement checks the exit code of the date command. If the input date string is a valid date value, the command returns 0. Otherwise, the exit code is non-zero.

We also added the “date … >/dev/null 2>&1redirection to redirect both stdout and stderr to /dev/null, effectively discarding any output from the date command.

Next, let’s test the script with some valid and invalid date strings:

$ ./validate_date.sh 1992-08-08
The input 1992-08-08 is a valid date string in the yyyy-mm-dd format.

$ ./validate_date.sh 1992-AUG-08
The input 1992-AUG-08 is NOT a valid date string in the yyyy-mm-dd format.

$ ./validate_date.sh 1992-42-42
The input 1992-42-42 is NOT a valid date string in the yyyy-mm-dd format.

$ ./validate_date.sh 0000-00-00
The input 0000-00-00 is NOT a valid date string in the yyyy-mm-dd format.

As the output shows, the script can check not only the argument’s format but also the validity of the date value.

3.2. Using gawk mktime() Function

awk is a powerful text processing tool. The widely used implementation GNU Awk provides a set of date- and time-related functions. For example, the mktime() function allows us to create a date time value from string values. The strftime() can convert a date value to a string in the required format.

Let’s first look at how we can perform the date validation using awk and then understand how it works:

$ cat validate_date_awk.sh 
#!/usr/bin/gawk -f

BEGIN{
    split(ARGV[1], array, /-/)
    ts = mktime(array[1] " " array[2] " " array[3] " 0 0 0")
    dtStr = strftime("%Y-%m-%d",ts)
    if ( ARGV[1] == dtStr )
        print "The input", ARGV[1], "is a valid date string in the yyyy-mm-dd format."
    else
        print "The input", ARGV[1], "is NOT a valid date string in the yyyy-mm-dd format."
}

So, as the script above shows, we perform the date validation in the following steps:

  • Extract year, month, and day from the input as the “yyyy-mm-dd” format using the split() function and save the extracted elements in an array (array)
  • Create a DateTime value (ts) using the mktime() function and the extracted elements. As we’re interested in the timestamp part, we fill in zeros for hour, minute, and second fields
  • Convert the ts date variable to a string (dtStr) using the strftime() function in the same format
  • Compare the initial input and the converted string. If they are equal, we can tell the input is valid

We may have noticed that we didn’t check if the input value is in the “yyyy-mm-dd” format. Instead, we called the split() function directly. This is because awk has a default value for undefined variables, such as 0 for numbers and an empty string for string variables. That’s to say, if the input isn’t in the required format, reading array[1], [2], or [3] will still get a value. In this case, the converted dtStr won’t be equal to the initial input. Thus, the validation won’t pass.

So finally, let’s test the awk script with some inputs:

$ ./validate_date_awk.sh 1992-08-08
The input 1992-08-08 is a valid date string in the yyyy-mm-dd format.

$ ./validate_date_awk.sh 1992-aug-08
The input 1992-aug-08 is NOT a valid date string in the yyyy-mm-dd format.

$ ./validate_date_awk.sh 0000-00-00
The input 0000-00-0 is NOT a valid date string in the yyyy-mm-dd format.

$ ./validate_date_awk.sh 1992-42-42
The input 1992-42-42 is NOT a valid date string in the yyyy-mm-dd format.

4. Conclusion

In this article, we’ve learned how to check if a string is in the “yyyy-mm-dd” date format.

Using Regex can straightforwardly check if the value matches the required format. However, it doesn’t guarantee that the value is a valid date.

So, we’ve learned two approaches using the date command and gawk to perform the date validation.