1590
Comment:
|
← Revision 4 as of 2014-12-19 21:07:32 ⇥
1647
No external math is needed if using GNU date.
|
Deletions are marked like this. | Additions are marked like this. |
Line 8: | Line 8: |
# get the seconds passed since Jan 1, 2010 (localtime) then=$(date -d "2010-01-01 00:00:00" +%s) |
# get the seconds passed since Jan 1, 2010 (local-time) then=$(date -d "2014-10-25 00:00:00" +%s) |
Line 12: | Line 12: |
# To avoid "Daylight Saving Time" aka "Daylight Savings Time", "DST" or "Summer Time" # and/or Local time adjustments, # is better to use UTC time: then=$(date -u -d "2014-10-25 00:00:00" +%s) now=$(date -u +%s) echo $(($now - $then)) |
|
Line 14: | Line 22: |
To print a duration as a human-readable value you'll have to do some math: | To print a duration as a human-readable value (within 365 days - 1 year) use {{{date}}} capacity to add and subtract time : |
Line 17: | Line 25: |
# some constants minute_secs=60 hour_secs=$((60 * minute_secs)) day_secs=$((24 * hour_secs)) # get total seconds_since=$(($now - $then)) # parse days=$((seconds_since / day_secs)) hours=$((seconds_since % day_secs / hour_secs)) minutes=$((seconds_since % day_secs % hour_secs / minute_secs)) seconds=$((seconds_since % day_secs % hour_secs % minute_secs)) # pretty-print echo "$days days, $hours hours, $minutes minutes and $seconds seconds." |
date -u -d "2014-01-01 $now sec - $then sec" +"%j days %T" |
Line 30: | Line 28: |
Or, without the verbose labels: | Or, a little more explicit: |
Line 32: | Line 31: |
# Bash/ksh ((duration = now - then)) ((days = duration / 86400)) ((duration %= 86400)) ((hours = duration / 3600)) ((duration %= 3600)) ((minutes = duration / 60)) ((seconds = duration % 60)) echo "$days days, $hours hours, $minutes minutes and $seconds seconds." |
date -u -d "2014-01-01 $now sec - $then sec" +"%j days %H hours %M minutes and %S seconds" |
Line 42: | Line 33: |
To print a duration that is longer than a year, you'll have to do some external additional math. The concept could be extended to nanoseconds, as this: {{{ then=$(date -u -d "2014-10-25 00:00:00" +"%s.%N") now=$(date -u +"%s.%N") date -u -d "2014-01-01 $now sec - $then sec" +"%j days %T.%N" # will print: 046 days 21:03:50.296901858 }}} |
|
Line 50: | Line 54: |
---- CategoryShell |
How to get the difference between two dates
It's best if you work with timestamps throughout your code, and then only convert timestamps to human-readable formats for output. If you must handle human-readable dates as input, then you will need something that can parse them.
Using GNU date, for example:
# get the seconds passed since Jan 1, 2010 (local-time) then=$(date -d "2014-10-25 00:00:00" +%s) now=$(date +%s) echo $(($now - $then)) # To avoid "Daylight Saving Time" aka "Daylight Savings Time", "DST" or "Summer Time" # and/or Local time adjustments, # is better to use UTC time: then=$(date -u -d "2014-10-25 00:00:00" +%s) now=$(date -u +%s) echo $(($now - $then))
To print a duration as a human-readable value (within 365 days - 1 year) use date capacity to add and subtract time :
date -u -d "2014-01-01 $now sec - $then sec" +"%j days %T"
Or, a little more explicit:
date -u -d "2014-01-01 $now sec - $then sec" +"%j days %H hours %M minutes and %S seconds"
To print a duration that is longer than a year, you'll have to do some external additional math.
The concept could be extended to nanoseconds, as this:
then=$(date -u -d "2014-10-25 00:00:00" +"%s.%N") now=$(date -u +"%s.%N") date -u -d "2014-01-01 $now sec - $then sec" +"%j days %T.%N" # will print: 046 days 21:03:50.296901858
To convert the timestamp back to a human-readable date, using recent GNU date:
date -d "@$now"
(See FAQ #70 for more about converting Unix timestamps into human-readable dates.)