Differences between revisions 3 and 4
Revision 3 as of 2010-07-30 13:46:05
Size: 1590
Editor: GreyCat
Comment:
Revision 4 as of 2014-12-19 21:07:32
Size: 1647
Editor: BinaryZebra
Comment: 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.)

BashFAQ/102 (last edited 2014-12-19 21:07:32 by BinaryZebra)