Masquerade
Masquerade

Reputation: 3890

Check if the date format is in ISO 8601 in bash

How can I validate that my datetime string has a valid ISO-8601 format with timezone (+0200) through a bash script?

The acceptable format is only %Y-%m-%dT%H:%M:%S+0200.

EDIT: I'm fine with having the year as 0001, 9999 or any random permutation of 4 digits. I just need to enforce the syntactical check.

Upvotes: 1

Views: 2390

Answers (3)

Timo Huovinen
Timo Huovinen

Reputation: 55643

If you want your ISO date to be validated for any timezone, including the format

1970-01-01T00:00:00Z
1970-01-01T00:00:00+0200

Then you can use this regex:

[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|\+[0-9]{4})$
#!/bin/bash

if [[ $1 =~ [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|\+[0-9]{4})$ ]]
then
  echo "ISO date";
else
  echo "Malformed date";
fi
  • Keep in mind that [[ ]] is not POSIX compliant, this limits its portability.

Upvotes: 1

anubhava
anubhava

Reputation: 785611

Here is a solution that doesn't use any regex and uses date parsing of gnu-date:

s='2021-08-23T12:10:35+200'

[[ $s == *'+200' && $(TZ=CET date -d "$s" '+%FT%T' 2>/dev/null) == "${s%+*}" ]] &&
echo 'ok' || echo 'nope'

Upvotes: 0

Jeff Schaller
Jeff Schaller

Reputation: 2557

Here's a simple bash script which tests the given parameter against a regex for an extended (not basic/shortened) ISO-8601 format which, following the question, requires all the fields to be present:

#!/bin/bash

if [[ $1 =~ ^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}T?[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}([\.,][[:digit:]]+)?\+0200$ ]]
then
  echo correct format
else
  echo incorrect format
fi

Wikipedia's article on ISO-8601 says that the format allows the omission of the day field, but the above regex requires it, following the question's example. The regex allows the T to be optional, following the Wikipedia article. I've added optional support for fractional seconds (the ([\.,][[:digit:]]+)? portion), again based on the Wikipedia article.

The regex does not do any range checking of the values.

Upvotes: 4

Related Questions