Reformat timestamp in a pipe delimited file

Those "timestamps" aren't seconds since the epoch as strftime() operates on, they're just dates+times with no separators between years, months, etc. You just need a simple text manipulation, not use of time functions.

With GNU awk (which you're already using) for gensub():

$ awk 'BEGIN{FS=OFS="|"} {$4=gensub(/(.{4})(..)(..)(..)(..)(..)/,"\\1-\\2-\\3 \\4:\\5:\\6",1,$4)} 1' file
John|Doe|TEST|2021-07-28 12:08:21|[email protected]
John|Davis|TEST|2021-08-28 12:08:21|[email protected]
John|Smith|TEST|2021-05-28 12:08:21|[email protected]

or with any awk:

$ awk 'BEGIN{FS=OFS="|"} {$4=sprintf("%s-%s-%s %s:%s:%s", substr($4,1,4), substr($4,5,2), substr($4,7,2), substr($4,9,2), substr($4,11,2), substr($4,13,2))} 1' file
John|Doe|TEST|2021-07-28 12:08:21|[email protected]
John|Davis|TEST|2021-08-28 12:08:21|[email protected]
John|Smith|TEST|2021-05-28 12:08:21|[email protected]

Assumption: The field to be changed is the only or first one that contains exactly 14 digits.

sed -E 's=\|([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})\|=|\1-\2-\3 \4:\5:\6|='

Your attempt fails because $4 would need to be the UNIX Epoch time (time in seconds since 1970), as the GNU Awk manual documents.


If you want to use a strftime-like method, then you could consider Miller, which also provides the corresponding strptime ex.

$ mlr --nidx --fs '|' put -S '
    $4 = strftime(strptime($4,"%Y%m%d%H%M%S"),"%Y-%m-%d %H:%M:%S")
  ' file
John|Doe|TEST|2021-07-28 12:08:21
John|Davis|TEST|2021-08-28 12:08:21
John|Smith|TEST|2021-05-28 12:08:21