I have two dates in forms like: YYYYMMDDHH
and want to calculate the differences (in hours) between these two dates. For example
start_date=1996010100
end_date=1996010122
which stands for two dates: 1996-01-01 00:00:00 and 1996-01-01 22:00:00. I want to use date
to calculate the difference in hours, the result shall be 22 hours. I tried with
START=$(date -d "$start_date" "%s")
END=$(date -d "$end_date" "%s")
HOURS=$(bc -l <<< "($END - $START) / 3600")
but it failed... So how can I do this? Thanks!
CodePudding user response:
which stands for two dates: 1996-01-01 00:00:00
So convert it to that form if it stands for it.
start_date=1996010100
start_date=$(sed -E 's/(....)(..)(..)(..)/\1-\2-\3 \4:00:00/' <<<"$start_date")
start=$(date -d "$start_date" "%s")
and the same with end.
CodePudding user response:
the most simple way is to install "dateutils" using this command
sudo apt-get install dateutils
Run these commands to get the difference in seconds:
dateutils.ddiff -i '%Y%m%d%H%M%S' 20200817040001 20210817040101
output:
31536060s
next step: Simply divide by 86400 to get the number of days or similarly for hours and minutes :)
CodePudding user response:
For performance reasons we want to limit the number of sub-process calls we need to invoke:
- use
bash
substring functionality to convert inputs into usable date/time strings - use
bash
math to replacebc
call
bash
substring functionality to break the inputs into a usable date/time format, eg:
# convert to usable date/time format:
$ start_date=1996010100
$ echo "${start_date:0:4}-${start_date:4:2}-${start_date:6:2} ${start_date:8:2}:00:00"
1996-01-01 00:00:00
# convert to epoch/seconds:
$ start=$(date -d "${start_date:0:4}-${start_date:4:2}-${start_date:6:2} ${start_date:8:2}:00:00" "%s")
$ echo $start
820476000
Applying to ${end_date}
and using bash
math:
$ end_date=1996010122
$ end=$(date -d "${end_date:0:4}-${end_date:4:2}-${end_date:6:2} ${end_date:8:2}:00:00" "%s")
$ echo $end
820555200
$ hours=$(( (end - start) / 3600))
$ echo $hours
22
This leaves us with 2 sub-process calls ($(date ...)
). While other languages/tools (awk
, perl
, etc) can likely speed this up a bit, if you need to store the result in a bash
variable then you're looking at needing at least 1 sub-process call (ie, hours=$(awk/perl/??? ...)
).
If performance is really important (eg, needing to perform this 1000's of times) take a look at this SO answer that uses a fifo, background date
process and io redirection ... yeah, a bit more coding and a bit more convoluted but also a bit faster for large volumes of operations.
CodePudding user response:
busybox date
can do the trick
start_date=1996010100
end_date=1996010122
START=$(busybox date -D "%Y%m%d%H" -d "$start_date" "%s")
END=$(busybox date -D "%Y%m%d%H" -d "$end_date" "%s")
HOURS=$(bc -l <<< "scale=0;($END - $START) / 3600")
echo $HOURS