'How to convert YYYYMMDDHHMMSS to a date readable by `date`

I have a set of date/time strings in the YYYYMMDDHHMMSS format that I want to convert to something readable by the date utility. Usually, I can do something like:

date -d "2010-10-01 12:34:56"

However, date does not like the YYYYMMDDHHMMSS:

date -d "20100101123456"..invalid date

So, I probably need to refine the string to be in the prior format. I'm thinking sed is the answer, but it gets ugly very fast. I'm quite certain my strings will be the proper format, so how do I easily convert them?



Solution 1:[1]

date doesn't allow "YYYYMMDDHHMMSS", but it does "YYYYMMDD HH:MM:SS", so:

D="20100101123456"
date -d "${D:0:8} ${D:8:2}:${D:10:2}:${D:12:2}"

Solution 2:[2]

If the format is totally fixed, you could just do it within bash, chopping up the string:

d=20100101123456
pretty_date="${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:${d:10:2}:${d:12:2}"
# 2010-01-01 12:34:56
...

I wouldn't bother trying to use regex - like you said, the pattern gets ugly fast. A lot of repetition of ([0-9]{4}), even with extended or perl regex. Or you could be flexible and just match .; no verification.

Solution 3:[3]

What's with all of these regular expression answers? The date(1) tool has the ability to use strftime() style date formatting... an an example of converting one date type to another:

$ date -j -f "%Y%m%d%H%M%S" "20100101123456" "+%Y-%m-%d %H:%M:%S"
2010-01-01 12:34:56

So if it's not in the format you want, convert it like that and then use it. If you just want to set it, you can simply do:

$ date -f "%Y%m%d%H%M%S" "20100101123456"

Solution 4:[4]

Try this:

echo "20101106213245" | sed -r 's/^.{8}/& /;:a; s/([ :])(..)\B/\1\2:/;ta'

Result:

20101106 21:32:45
  • Insert a space after the eighth character
  • [label a] After a space or colon and the next two characters, add a colon
  • If a replacement was made, goto label a

You want some hyphens, too?

echo "20101106213245" | sed -r 's/^.{4}/&-/;:a; s/([-:])(..)\B/\1\2:/;ta;s/:/-/;s/:/ /'

Result:

2010-11-06 21:32:45
  • Insert a hyphen after the fourth character
  • [label a] After a hyphen or colon and the next two characters, add a colon
  • If a replacement was made, goto label a
  • Change the first colon to a hyphen (2010-11:06:21:32:45 -> 2010-11-06:21:32:45)
  • Change the next colon to a space (2010-11-06:21:32:45 -> 2010-11-06 21:32:45)

Solution 5:[5]

 sed -ne 's/\(....\)\(..\)\(..\)\(..\)\(..\)\(..\)/\1-\2-\3 \4:\5:\6/p'

I admit it'S a mouthful. All the .'s should optimally be [0-9] or \d, though I don't remember if sed supports the latter.

Solution 6:[6]

Either busybox date or bsd date accept a description of the input format.

Busybox is a GNU small utility, easy to install.

The bsd format has been covered in another answer, so here is busybox:

$ busybox date -D "%Y%m%d%H%M%S" -d "20100101123456" +'%Y-%m-%d %H:%M:%S'
2010-01-01 12:34:56

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 chris
Solution 2 Cascabel
Solution 3
Solution 4 Dennis Williamson
Solution 5 Ulrich Schwarz
Solution 6 Cadoiz