How do I convert the number of seconds passed since 1 January 2001 00:00 to human readable date in bash?

Since Unix' Epoch is 1970-01-01 00:00:00 UTC rather than 2001-01-01 00:00:00 UTC, available tools, like the gnu date command, must just be supplied the seconds between both in addition to the actual data to give the result using their built-in conversion features.

$ seconds=500000
$ TZ=UTC date --iso-8601=s -d @$(( $(date +%s -d '2001-01-01T00:00:00+00') + $seconds ))
2001-01-06T18:53:20+00:00

UPDATE: (thanks to @Kusalananda's comment) actually there's not even the need to mention Unix Epoch, because the GNU date command accepts directly adding a time offset to a given date. It must just be supplied with the correct unit suffix (here seconds). This makes the command simplier, more generic, and easier to read:

$ seconds=500000
$ TZ=UTC date --iso-8601=s -d "2001-01-01T00:00:00+00 + $seconds seconds"
2001-01-06T18:53:20+00:00

To output exactly like OP's output format, replace --iso-8601=s with '+%F %T %z'

Above command uses those options and parameters:

  • -d: use given date rather than current date. Can include additions of time offsets.
  • --iso-8601=s is the ISO format similar to (give or take some spaces etc.) +%F %T %z which is same as +Y-%m-%d %H:%M:%S %z: self explanatory, with %z the timezone offset to UTC, which here will be +0000 since TZ=UTC forced it.

Using an awk implementation that supports mktime() and strftime() (such as mawk or GNU awk):

$ awk 'BEGIN { epoch = mktime("2001 01 01 00 00 00"); print strftime("%F %T %z", epoch + 500000) }'
2001-01-06 18:53:20 +0000

This first creates a UNIX timestamp corresponding to 2001-01-01 at 00:00, and then adds 500000 seconds to that and formats and prints the result according to the strftime() format string. The computations here are done in local time.

With the seconds taken from an argument on the command line:

awk -v offset=500000 '
    BEGIN { epoch = mktime("2001 01 01 00 00 00")
            print strftime("%F %T %z", epoch + offset) }'

Reading the seconds from standard input (the first word on each line):

awk 'BEGIN { epoch = mktime("2001 01 01 00 00 00") }
           { print strftime("%F %T %z", epoch + $1)   }'

See your awk manual for a description of the mktime() and strftime() functions, and also see man strftime for the available format strings.

Set the TZ environment variable to UTC for doing calculations and output in UTC rather than local time:

TZ=UTC awk ...as above...

Tags:

Bash

Date