152

The date time string is in the following format: 06/12/2012 07:21:22. How can I convert it to UNIX timestamp or epoch?

9 Answers 9

134

What you're looking for is date --date='06/12/2012 07:21:22' +"%s". Keep in mind that this assumes you're using GNU coreutils, as both --date and the %s format string are GNU extensions. POSIX doesn't specify either of those, so there is no portable way of making such conversion even on POSIX compliant systems.

Consult the appropriate manual page for other versions of date.

Note: bash --date and -d option expects the date in US or ISO8601 format, i.e. mm/dd/yyyy or yyyy-mm-dd, not in UK, EU, or any other format.

Sign up to request clarification or add additional context in comments.

8 Comments

I get 'date: illegal option --' when I run on Mac OSX 10.8.2
For noobs like me +"%s" stands for output format and %s is the format of time in seconds since 1970
Note: if you want to specify the time in another timezone (like UTC) add -HHMM or +HHMM to the end. So date --date='06/12/2012 07:21:22 -0000' +"%s" converts UTC date to unix time stamp
For GNU date, if you wish to use UTC note that the format is yyyy-mm-dd hh:mm:sshave a look at gnu.org/software/coreutils/manual/html_node/… : gdate --date='2019-06-18 00:02:00 +0000' +%s
@nonopolarity On my mac with gnu coreutils, the command is called gdate instead of date. I can run the above command from @Daniel Kamil Kozar using: gdate --date='06/12/2012 07:21:22' +"%s" which in turn gives me: 1339510882
|
92

For Linux, run this command:

date -d '06/12/2012 07:21:22' +"%s" 

For macOS, run this command:

date -jf "%Y-%m-%d %H:%M:%S" "1970-01-01 00:00:00" +%s 

8 Comments

On OSX the timestamp increases somehow with the current time. I currently don't have an explanation for that...
Update: That was because it adjusts the timestamp for my localtime I guess... Adding a -u flag should fix that.
@AbdulRehmanJanjua The -u flag should come before the -f flag, or else the shell interprets it the format string. So, it should be: date -j -u -f "%a..."
Pasting exactly that in a macOS terminal fails.
date -jf "%Y-%m-%d %H:%M:%S" "2018-01-08 14:45:00" +%s
|
16

A lot of these answers are overly complicated and also are missing how to use variables. This is how you would do it more simply on standard Linux system (as previously mentioned the date command would have to be adjusted for Mac Users) :

Sample script:

#!/bin/bash orig="Apr 28 07:50:01" epoch=$(date -d "${orig}" +"%s") epoch_to_date=$(date -d @$epoch +%Y%m%d_%H%M%S) echo "RESULTS:" echo "original = $orig" echo "epoch conv = $epoch" echo "epoch to human readable time stamp = $epoch_to_date" 

Results in :

RESULTS: original = Apr 28 07:50:01 epoch conv = 1524916201 epoch to human readable time stamp = 20180428_075001 

Or as a function :

# -- Converts from human to epoch or epoch to human, specifically "Apr 28 07:50:01" human. # typeset now=$(date +"%s") # typeset now_human_date=$(convert_cron_time "human" "$now") function convert_cron_time() { case "${1,,}" in epoch) # human to epoch (eg. "Apr 28 07:50:01" to 1524916201) echo $(date -d "${2}" +"%s") ;; human) # epoch to human (eg. 1524916201 to "Apr 28 07:50:01") echo $(date -d "@${2}" +"%b %d %H:%M:%S") ;; esac } 

2 Comments

And this in not overly complicated, e.g. when compared with stackoverflow.com/a/27978453/6607497?
No it's about the same ..
8

Just be sure what timezone you want to use.

datetime="06/12/2012 07:21:22" 

Most popular use takes machine timezone.

date -d "$datetime" +"%s" #depends on local timezone, my output = "1339456882" 

But in case you intentionally want to pass UTC datetime and you want proper timezone you need to add -u flag. Otherwise you convert it from your local timezone.

date -u -d "$datetime" +"%s" #general output = "1339485682" 

2 Comments

What if my date format is "YYYYmmdd"? ex. 20200827
You can use it as well. date formats properly this input.
8

Efficient way to convert date time string to epoch in bash

Avoiding useless repetitives forks, in order to make this translation a lot quicker...

Instead of running 1 fork for each translation, we could run date -f - +%s as background process...

Intro

Common syntax:

epochDate=$(date -d "$InputDate" +%s) 

Work fine, but become heavy if run repetetively!

In this post, you will find

  • a Quick Demo, following this,
  • some Explanations,
  • a Function useable for many Un*x tools (bc, rot13, sed...).

Quick Demo using coproc

coproc DATE { exec stdbuf -o0 /bin/date -f - +%s 2>&1 ;} echo >&${DATE[1]} 06/12/2012 07:21:22 read -ru${DATE[0]} epochDate printf 'EPOCH: %u Date:%(%c)T\n' $epochDate $epochDate 
EPOCH: 1339478482 Date:Tue Jun 12 07:21:22 2012 

About performances, you could compare:

time for i in {1..900};do echo >&${DATE[1]} "now";read -ru${DATE[0]} ans;done real 0m0.029s user 0m0.018s sys 0m0.005s 

and:

time for i in {1..900};do ans=$(date +%s -d "now");done real 0m1.465s user 0m0.962s sys 0m0.442s 

From more than 1.4 seconds to less than 30 milliseconds!!(on my host).

You could check echo $ans, replace "now" by "2019-25-12 20:10:00" and so on...

Little function

myDate() { if [[ $1 == -v ]]; then local -n out=$2 shift 2 else local out fi echo "$*" >&${DATE[1]} read -ru ${DATE[0]} out [[ ${out@A} == out=* ]] && echo $out case $out in ''|*[!0-9]*) return 1;; esac } 
myDate 06/12/2012 07:21:22 
1339478482 
myDate -v var 06/12/2012 07:21:22 printf '%(%c)T\n' $var 
Tue Jun 12 07:21:22 2012 
myDate -v var wrong string printf 'ResultCode: %d: Var: "%s"\n' "$?" "$var" 
ResultCode: 1: Var: "/bin/date: invalid date 'wrong string'" 

Stop background

You could, once requirement of date subprocess ended:

kill ${DATE_PID} exec {DATE[1]}>&- ; exec {DATE[0]}<&- 
[1]+ Terminated coproc DATE { exec stdbuf -o0 /bin/date -f - +%s; } 

Original post (detailed explanation)

Instead of running 1 fork by date to convert, run date just 1 time and do all convertion with same process (this could become a lot quicker)!:

date -f - +%s <<eof Apr 17 2014 May 21 2012 Mar 8 00:07 Feb 11 00:09 eof 1397685600 1337551200 1520464020 1518304140 

Sample:

start1=$(LANG=C ps ho lstart 1) start2=$(LANG=C ps ho lstart $$) dirchg=$(LANG=C date -r .) read -p "A date: " userdate { read start1 ; read start2 ; read dirchg ; read userdate ;} < <( date -f - +%s <<<"$start1"$'\n'"$start2"$'\n'"$dirchg"$'\n'"$userdate" ) 

Then now have a look:

declare -p start1 start2 dirchg userdate 

(may answer something like:

declare -- start1="1518549549" declare -- start2="1520183716" declare -- dirchg="1520601919" declare -- userdate="1397685600" 

This was done in only one date subprocess execution!

Using long running subprocess

We just need one fifo:

mkfifo /tmp/myDateFifo exec 7> >(exec stdbuf -o0 /bin/date -f - +%s >/tmp/myDateFifo) exec 8</tmp/myDateFifo rm /tmp/myDateFifo 

(Note: As process is running and all descriptors are opened, we could safely remove fifo's filesystem entry.)

Then now:

LANG=C ps ho lstart 1 $$ >&7 read -u 8 start1 read -u 8 start2 LANG=C date -r . >&7 read -u 8 dirchg read -p "Some date: " userdate echo >&7 $userdate read -u 8 userdate 

We could buid a little function:

mydate() { local var=$1; shift; echo >&7 $@ read -u 8 $var } mydate start1 $(LANG=C ps ho lstart 1) echo $start1 

Or use my newConnector function

With functions for connecting MySQL/MariaDB, PostgreSQL and SQLite...

You may find them in different version on GitHub, or on my site: download or show.

wget https://raw.githubusercontent.com/F-Hauri/Connector-bash/master/shell_connector.bash 
wget http://f-hauri.ch/vrac/shell_connector.sh . shell_connector.bash newConnector /bin/date '-f - +%s' @0 0 myDate "2018-1-1 12:00" test echo $test 1514804400 

Nota: On GitHub, functions and test are separated files. On my site test are run simply if this script is not sourced. On GitHub, there is no upgrade anymore! Last verified version is on my site!

# Exit here if script is sourced [ "$0" = "$BASH_SOURCE" ] || { true;return 0;} 

5 Comments

How is this very long answer related to the question asked?
@U.Windl: Question is How can I convert time string to UNIX timestamp. My answer address precisely this and offer way to process this operation repetitively, usinf and efficient and system friendly method. Try this for sample: for i in {1..900};do ans=$(date +%s -d "06/12/2012 07:21:22");done using my method, this will take some milliseconds! Addressing POSIX shell and bash
Given that stackoverflow.com/a/27978453/6607497 existed long before, what does your answer add? The question did not mention that there are many such timestamps to convert. Also I think the complexity of your answer is too much for most of the users. Specifically I see the danger of running code people don't really understand. I'm not saying your solution isn't "cool".
@U.Windl what does your answer add? Application of -f switch for GNU date usage sample.
@U.Windl In fact, this answer is a kind of attempt to parallelization introduction! Think parallel!
4
get_curr_date () { # get unix time DATE=$(date +%s) echo "DATE_CURR : "$DATE } conv_utime_hread () { # convert unix time to human readable format DATE_HREAD=$(date -d @$DATE +%Y%m%d_%H%M%S) echo "DATE_HREAD : "$DATE_HREAD } 

1 Comment

Welcome to Stack Overflow. Consider adding an explanation in addition to your code.
0

I added the following alias to .bashrc (or .zshrc) - note the --utc switch which converts the input as UTC time zone. You can remove it to use the local machine time zone but in my experience I usually want UTC for this:

alias datetoepoch='date --utc +%s -d' 

Now I can just type in the terminal something like:

datetoepoch 2024-03-18 

and get the result:

1710720000

Comments

0

Not exactly asked for, but I use this to convert an OpenLDAP timestamp like 20241111073923Z to seconds since the epoch:

echo $(date -u --date=$(echo "$1" | sed \ -e 's/^\(....\)\(..\)\(..\)\(..\)\(..\)\(..\)Z$/\1-\2-\3T\4:\5:\6/') '+%s') 

For the example timestamp the command executed will be date -u --date=2024-11-11T07:39:23 +%s, and the output will be 1731310763.

Comments

0

A bash function is always faster than exec date, here is the code I used to convert datetime to epoch seconds for computing seconds difference between datetimes. However the timezone is ignored, so it's not exactly epoch seconds. While it could be easy to add timezone offset seconds.

 if [ "${datetime/ /}" != "$datetime" ]; then date="${datetime% *}" time="${datetime##* }" else date="${datetime%-*}" time="${datetime##*-}" fi if [ "${date/-/}" != "$date" ]; then year="${date%%-*}" s="${date#*-}" month=$(( 1"${s%%-*}" - 100 )) day=$(( 1"${s#*-}" - 100 )) else year=${date:0:4} month=$(( 1"${date:4:2}" - 100 )) day=$(( 1"${date:6:2}" - 100 )) fi if [ "${time/:/}" != "$time" ]; then hour=${time%%:*} s=${time#*:} minute=$(( 1"${s%%:*}" - 100 )) second=$(( 1"${s#*:}" - 100 )) else hour=$(( 1"${time:0:2}" - 100 )) minute=$(( 1"${time:2:2}" - 100 )) second=$(( 1"${time:4:2}" - 100 )) fi month0=$(( month - 1 )) day0=$(( day - 1 )) if [ $((year % 100)) == 0 ]; then leap=$(( year % 400 == 0 )) else leap=$(( year % 4 == 0 )) fi if [ $leap == 1 ]; then mo=(31 29 31 30 31 30 31 31 30 31 30 31) mobase=(0 31 60 91 121 152 182 213 244 274 305 335) else mo=(31 28 31 30 31 30 31 31 30 31 30 31) mobase=(0 31 59 90 120 151 181 212 243 273 304 334) fi days_1970=$(( 1970 * 365 + 1970 / 4 - 1970 / 100 + 1970 / 400 )) days_0=$(( year * 365 + year / 4 - year / 100 + year / 400 )) epochday=$(( days_0 - days_1970 + mobase[month0] + day0 )) epochsec=$(( epochday * 86400 + (hour * 60 + minute) * 60 + second )) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.