I would like to write a script or function to tell me how many days from now until a given date in the future. What I'm struggling to work out is how to process the given date and compare it with the current date... I'm imagining something like
read -p "enter the date in the format YYYY-MM-DD "
And then I'm assuming I have a string that's meaningless to the shell and I have to do some evaluations like...?? (This is just an example; I guess bc
would be needed)
i=$(($(date +%Y)-${REPLY%%-*}))
j=$(($(date +%m)-${REPLY:5:2}))
k=$(($(date +%d)-${REPLY##*-}))
And then I don't know what to do with those numbers...??
if $i > 1 then assign l=$((i*365)) and else what?? # what about leap years?
Using $j somehow assign m # confused before I've started
Using $k somehow assign n # just as bad
echo $((l+m+n))
I'm surely making it too hard for myself; probably there's a text processing tool that understands dates and can compare them.
How can I do this?
Epoch time
In general, calculations on time are easiest if we first convert time into (Unix) epoch time (seconds from 1-1-1970). In python, we have tools to convert time into epoch time, and back into any date format we prefer.
We can simply set a format, like:
...and define today:
and subsequently write a function to do the job:
Then the output of:
...which is, as mentioned, the number of seconds since 1-1-1970
Calculating the days between two dates
If we do this on both today and our future date, subsequently calculate the difference:
The output will be calculated by date, since we use the format
%Y-%m-%d
. Rounding on seconds would possibly give an incorrect date difference, if we are near 24 hrs for example.Terminal version
...And the Zenity option
And just for fun...
A tiny application. Add it to a shortcut if you use it often.
The script:
orangedays.py
Run it:
To wrap it up
Use for the tiny application script above the following
.desktop
file:orangedays.desktop
in~/.local/share/applications
In the line
set the actual path to the script...
The GNU
date
utility is quite good at this sort of thing. It is able to parse a good variety of date formats and then output in another format. Here we use%s
to output the number of seconds since the epoch. It is then a simple matter of arithmetic to subtract$now
from the$future
and divide by 86400 seconds/day:You could try doing something in
awk
, using themktime
functionThe awk expects to read date from standard input in the format "YYYY MM DD HH MM SS" and then prints the difference between the time specified and the current time in days.
mktime
simply converts a time (in the specified format) to the number of seconds from a reference time (1970-01-01 00:00:00 UTC); systime simple specifies the current time in the same format. Subtract one from the other and you get how far apart they are in seconds. Divide by 86400 (24 * 60 * 60) to convert to days.Here is a Ruby version
Example Run:
Example run of the script
ruby ./day-difference.rb
is given below (assuming you have saved it asday-difference.rb
)With a future date
With a passed date
When passed today's date
Here is an nice website to check the differences of date http://www.timeanddate.com/date/duration.html
There is a
dateutils
package which is very convenient for dealing with dates. Read more about it here github:dateutilsInstall it by
sudo apt install dateutils
For your problem, simply,
dateutils.ddiff <start date> <end date> -f "%d days"
where the output can be chosen as seconds, minues, hours, days, weeks, months or years. It can be conveniently used in scripts where the output can be used for other tasks.
For example,
You can use the awk Velour library:
Or:
A short solution, if both dates belong to the same year, is:
using the "%j"-format, which returns position of date in days in year, i.e. 135 for the current date. It avoids rounding problems and handles dates in the past, giving negative results.
However, crossing year borders, this will fail. You could add (or subtract) 365 manually for each year or 366 for each leap year, if the last of February is crossed, but that will be nearly as verbose as other solutions.
Here the pure bash solution:
Shellcheck suggests a lot of double quoting, but for days exceeding the year 9999 you should consider a different approach. For the past, it will fail silently for dates before 1970.01.01. Sanitizing user input is left as an exercise to the user.
The two functions can be refactored into one, but that might make it harder to understand.
Please note, that the script needs exhaustive testing for handling leap years in the past correctly. I wouldn't bet it is right.