I am trying to compare 2 dates in the format YYYY:MM:DD HH:MM:SS by using the date (bash) command. My problem is that the date command only uses the date format (as far as I know) YYYY-MM-DD HH:MM:SS. I was trying to use sed with regular expressions to replace the first 2 occurrences of : with - but I was not able to get it to work. I’m only getting 2018.

date1="2018:01:16 12:25:35"
echo $date1 | sed 's/\([0-9]*\).*/\1/'

I’ll take any possible suggestions and thank you.

  • How do you want to compare them? Put them in date order, or after a particular date or..? As Jeff shows below, you can change the date commands output format. gnu.org/software/coreutils/manual/html_node/…
    – Guy
    Commented Jan 18, 2018 at 0:58
  • I have an array that will store the dates and a couple of loops will sort them but the issue is that in order for me to sort them I need to compare them and I need for them to be in the format mentioned in the question.
    – Fxbaez
    Commented Jan 18, 2018 at 1:05
  • I think it would be sed -E ‘s/([[:digit:]]{4}):([[:digit:]]{2}):([[:digit:]]{2})(.*)/\1-\2-\3\4/‘ maybe. Capture year, month, day, and rest, and reprint.
    – Guy
    Commented Jan 18, 2018 at 1:14
  • 1
    With GNU sed you could replace all of the colons - then swap back from the third onward e.g. 's/:/-/g; s/-/:/3g' Commented Jan 18, 2018 at 1:20
  • 2
    you should fix the problem at the source if you can - i.e. fix whatever it is that's producing dates in that bogus format. Nobody uses : as separator between year, month, day.
    – cas
    Commented Jan 18, 2018 at 2:28

7 Answers 7


Just do a simple substitution twice:

sed 's/:/-/;s/:/-/'
  • or even sed 's/:/-/;s//-/' file
    – potong
    Commented Jun 12, 2021 at 10:07

[Answering the question as asked - although it's likely not the best way to approach your actual date comparison problem]

One way would be to replace colons one at a time using a loop, breaking out of the loop when the result contains two hyphens:

echo '2018:01:16 12:25:35' | sed ':a; /^[^-]*-[^-]*-/ b; s/:/-/; ta'
2018-01-16 12:25:35

Alternatively, if you have GNU sed, you could replace all the colons with hyphens, then replace from the third hyphen onward with colons again:

echo '2018:01:16 12:25:35' | sed 'y/:/-/; s/-/:/3g'
2018-01-16 12:25:35
  • Lets say that I have 2 dates with my original format YYYY:MM:DD HH:MM:SS .. how would you suggest that I compare the 2 dates?
    – Fxbaez
    Commented Jan 18, 2018 at 1:39
  • @Fxbaez you can use test and [[ ... ]] in the shell to check ordering, or even just use sort depending on what you actually need to do.
    – Guy
    Commented Jan 18, 2018 at 2:29
  • s/:/-/g can be replaced by y/:/-/
    – potong
    Commented Jun 12, 2021 at 10:09
  • @potong good point - let's give the y command some love... Commented Jun 12, 2021 at 13:36
| sed 's/\([0-9]*\).*/\1/'

This saves the first string of digits, eats everything after that with the .* then puts those digits back, so indeed anything after the 2018 disappears.

You'd need to capture the first two strings of digits, plus the separators to replace them, and not match the rest of the line:

$ echo "2018:01:16 12:25:35" | sed 's/\(....\):\(..\):/\1-\2-/'
2018-01-16 12:25:35

Consider using the GNU date command directly:

date1=$(date +”%Y-%m-%d %H-%M-%S”)
  • Im trying to change the format as you suggested and storing it in a new variable called date2 by typing this command. date2=$(date - - date=“$date1” +”%Y-%M-%D %H:%M:%S”) and I get invalid date ... any additional suggestions?
    – Fxbaez
    Commented Jan 18, 2018 at 1:10
  • Your proposed solution generates the date with the format based on the current date not the date that I would like to specify.
    – Fxbaez
    Commented Jan 18, 2018 at 1:15
  • @Fxbaez In Unix commands, spaces count. Remove the spaces from - - date.
    – John1024
    Commented Jan 18, 2018 at 1:29
  • GNU date can't parse a date with : separating Y,M,D. date: invalid date '2018:01:16 12:25:35'. that's the point of this question.
    – cas
    Commented Jan 18, 2018 at 2:33

I have used below 2 methods to achieve the mentioned result

method1 using awk gsub function

echo $date1| awk '{gsub(":","-",$1);print $0}'

output 2018-01-16 12:25:35

Method2 using sed

echo $date1 |sed "s/:/-/"| sed "s/:/-/"

output 2018-01-16 12:25:35

Method3 using perl

echo $date1| perl -pne "s/:/-/"| perl -pne "s/:/-/"

output 2018-01-16 12:25:35


Substitution expressions in sed support a numeric flag. Here's how GNU sed can do it:

sed 's/:/-/g;s/-/:/3g'

So what's going on here? This expression has two parts, separated by ;. Here they are:

  1. First, replace all colons with hypens
  2. Then replace all hyphens except the first 2 with colons

This isn't generally useful in cases where your initial string has hyphens or colons that could interfere, but it does work on your date-string example.

Re. exiftool

That said, I wonder if you're getting your colon-formatted date from exiftool because I've seen that as its default date format. With exiftool, you can just specify a different date format:

exiftool -d '%Y-%m-%d %H:%M:%S' some-input-file.jpg

When you mix sed's g and number modifiers

Note: the POSIX standard does not specify what should happen when you mix the g and number modifiers, and currently there is no widely agreed upon meaning across sed implementations. For GNU sed, the interaction is defined to be: ignore matches before the numberth, and then match and replace all matches from the numberth on. [source]

date1="2018:01:16 12:25:35"
bo=date1.split(" ")
print jk+" "+bo[1]


2018-01-16 12:25:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .