289

How do I convert an epoch timestamp to a human readable format on the cli? I think there's a way to do it with date but the syntax eludes me (other ways welcome).

0

12 Answers 12

433

On *BSD:

date -r 1234567890

On Linux (specifically, with GNU coreutils ≥5.3):

date -d @1234567890

With older versions of GNU date, you can calculate the relative difference to the UTC epoch:

date -d '1970-01-01 UTC + 1234567890 seconds'

If you need portability, you're out of luck. The only time you can format with a POSIX shell command (without doing the calculation yourself) line is the current time. In practice, Perl is often available:

perl -le 'print scalar localtime $ARGV[0]' 1234567890
9
  • 7
    +1 for the comment about the lack of portability (why doesn't the POSIX spec include a way to do this? grr) Feb 1, 2012 at 22:50
  • 6
    What does the @ mean in date -d @1234567890? man date made no reference to that... Jan 14, 2013 at 21:10
  • 12
    @ChrisMarkle GNU man pages are often woefully incomplete. “The date string format is more complex than is easily documented here but is fully described in the info documentation.” To wit: gnu.org/software/coreutils/manual/html_node/… Jan 14, 2013 at 21:56
  • 4
    The info date is quite complete. The entry at 28.9 Seconds since the Epoch explains in detail about the @timestamp.
    – user79743
    Feb 10, 2016 at 8:31
  • 1
    To display the date in UTC, add the -u option.
    – ma11hew28
    Jun 27, 2020 at 12:45
40

If your epoch time is in milliseconds instead of seconds, either put a dot before last three digits (as hinted in comments by user79743), or remove the last three digits before passing it to date -d:

Entered directly, this gives incorrect result :

$ date -d @1455086371603
Tue Nov  7 02:46:43 PST 48079     #Incorrect

Put a dot before last three digits:

$ date -d @1455086371.603
Tue Feb  9 22:39:32 PST 2016     #Correct

Or, remove the last three digits:

$ date -d @1455086371
Tue Feb  9 22:39:31 PST 2016      #Correct after removing the last three digits. You may remove and round off the last digit too.
5
  • What utility prints included milliseconds (without a dot) ?
    – user79743
    Feb 10, 2016 at 8:35
  • 1
    I have seen that WebLogic Application server mostly returns data time values with milliseconds and no dots when using scripting tool. e.g., lastSuccessfulConnectionUse=1455086371603 Feb 10, 2016 at 8:49
  • I see. This page confirms Raw Time Value The timestamp in milliseconds. Thanks.
    – user79743
    Feb 10, 2016 at 10:11
  • 1
    Atlassian tools log their timestamps as epoch time with milliseconds.
    – Br.Bill
    Mar 7, 2019 at 21:09
  • This doesn't work on HP-UX.
    – saulius2
    Sep 3, 2020 at 6:52
31

date -d @1190000000 Replace 1190000000 with your epoch

4
21

With bash-4.2 or above:

$ printf '%(%FT%T%z)T\n' 1234567890
2009-02-13T23:31:30+0000

(where %FT%T%z is the strftime()-type format, here using standard unambiguous format which includes the UTC offset (%z))

That syntax is inspired from ksh93.

In ksh93 however, the argument is taken as a date expression where various and hardly documented formats are supported.

For a Unix epoch time, the syntax in ksh93 is:

printf '%(%FT%T%z)T\n' '#1234567890'

ksh93 however seems to use its own algorithm for the timezone and can get it wrong. For instance, in mainland Britain, it was summer time all year in 1970, but:

$ TZ=Europe/London bash -c 'printf "%(%c)T\n" 0'
Thu 01 Jan 1970 01:00:00 BST
$ TZ=Europe/London ksh93 -c 'printf "%(%c)T\n" "#0"'
Thu Jan  1 00:00:00 1970

ksh93 (and zsh's strftime builtin) support subsecond, not bash yet:

$ ksh -c 'printf "%(%FT%T.%6N%z)T\n" 1234567890.123456789'
2009-02-13T23:31:30.123456-0000
$ zsh -c 'zmodload zsh/datetime; strftime %FT%T.%6.%z 1234567890 123456780'
2009-02-13T23:31:30.123457+0000
1
  • This actually works on HP-UX. Thanks!
    – saulius2
    Sep 3, 2020 at 7:18
20

Custom format with GNU date:

date -d @1234567890 +'%Y-%m-%d %H:%M:%S'

Or with GNU awk:

awk 'BEGIN { print strftime("%Y-%m-%d %H:%M:%S", 1234567890); }'

Linked SO question: https://stackoverflow.com/questions/3249827/convert-from-unixtime-at-command-line

1
  • 4
    Only works for GNU date and GNU awk. Neither awk nor nawk support strftime.
    – user14755
    Jul 28, 2014 at 3:56
16
$ echo 1190000000 | perl -pe 's/(\d+)/localtime($1)/e' 
Sun Sep 16 20:33:20 2007

This can come in handy for those applications which use epoch time in the logfiles:

$ tail -f /var/log/nagios/nagios.log | perl -pe 's/(\d+)/localtime($1)/e'
[Thu May 13 10:15:46 2010] EXTERNAL COMMAND: PROCESS_SERVICE_CHECK_RESULT;HOSTA;check_raid;0;check_raid.pl: OK (Unit 0 on Controller 0 is OK)
10

The two I frequently use are:

$ perl -leprint\ scalar\ localtime\ 1234567890
Sat Feb 14 00:31:30 2009

and

$ tclsh
% clock format 1234567890
Sa Feb 14 00:31:30 CET 2009
2
  • 1
    Love this tclsh suggestion, that seems much easier to remember than most of the incantations in this thread
    – phette23
    Aug 10, 2021 at 19:09
  • The perl one worked for me with timestamp formated like 1.679703228911E9
    – Pierre
    Mar 31, 2023 at 10:05
9

With zsh you could use the strftime builtin:

strftime format epochtime

      Output the date denoted by epochtime in the format specified.

e.g.

zmodload zsh/datetime
strftime '%A, %d %b %Y' 1234567890
Friday, 13 Feb 2009

There's also dateconv from dateutils:

dateconv -i '%s' -f '%A, %d %b %Y' 1234567890
Friday, 13 Feb 2009

keep in mind dateutils tools default to UTC (add -z your/timezone if needed).

2
  • It doesn't look like dateutils is available on HP-UX.
    – saulius2
    Sep 3, 2020 at 7:10
  • On Debian, the dateutils package has the dateutils.dconv binary instead of dateconv. I'm assuming it's the same thing, but renamed.
    – cstroe
    Jul 28, 2022 at 16:32
1

In PowerShell:

(([System.DateTimeOffset]::FromUnixTimeMilliSeconds($unixtime)).DateTime).ToString("s")
5
0

You could also use a little C program for printing the datetime in the format that can be directly parsed by shell

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main(int argc, char * argv[]) {

    if (argc==1) { 
        return 1;
    }

    struct tm input_tm;
    char * formatStr  = "YEAR=%Y\nMON=%m\nDAY=%d\nHOUR=%H\nMIN=%M\nSEC=%S";
    size_t formatSize = strlen(formatStr) + 2;
    char * output     = (char *)malloc(sizeof(char)*formatSize);

    strptime(argv[1],"%s",&input_tm);
    strftime(output, formatSize, formatStr, &input_tm);

    printf("%s\n",output);
    free(output);
    return 0;
}

usage:

#compile
clang -o epoch2datetime main.c

#invoke
eval `./epoch2datetime 1450196411`
echo $YEAR $MON $DAY $HOUR $MIN $SEC
#output
#2015 12 16 00 20 11
3
  • 1
    Doesn't work on HP-UX: ./a.out 1599099168 YEAR=1901 MON=03 DAY=00 HOUR=2130568304 MIN=
    – saulius2
    Sep 3, 2020 at 7:16
  • @saulius2 ... what? I completely believe you, but the situation is kind of crazy. HP-UX can't correctly handle stdio.h, stdlib.h, string.h, and time.h in Standard (ANSI/ISO) C !?!?!? . . . . . . . . . . . . . . . . What the for i in {1..4}; do ascii_base10_val=$(echo "33+$(shuf -i 0-14 -n 1)" | bc -l); ascii_hex_val=$(echo "obase=16; ${ascii_base10_val}" | bc); printf "\x${ascii_hex_val}"; done; echo has HP-UX done! . . . . . . . . . . . . . . . . . . . . . . . . . (The code will give a cartoon representation of a cuss word, by the way.) Aug 18, 2022 at 21:27
  • Well, I didn't investigate at the time, and now I have lost access to these HP-UX boxes, so I cannot investigate at the moment too.
    – saulius2
    Aug 19, 2022 at 7:35
0

Wouldn't be a real solution without a little node.js:

epoch2date(){
    node -p "new Date($1)"
}

add that to ~/.bash_aliases and make sure its sourced in ~/.bashrc with . ~/.bash_aliases

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

To get node on your system goto http://nvm.sh and run the curl command. It'll install node version manager (nvm) which allows you to switch versions of node.

Just type nvm ls-remote and pick a version to nvm install <version>.

1
0

If UTC is your preference (for the sample epoch timestamp 1666666666),

$ # long options; Linux
$ date --date=@1666666666 --utc
Tue 14 Nov 22:13:20 UTC 2023

$ # short options; Linux
$ date -d @1666666666 -u
Tue 14 Nov 22:13:20 UTC 2023

You must log in to answer this question.

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