where the “%s” means report the number of seconds since the reference date of 1/1/2007 and 86400 is the number seconds in one day.
A minor irritation is that I have to specify the subtractant date in USA format, i.e. mm/dd/yyyy rather than my UK locale format of dd/mm/yyyy.
Curiously my locale is set correctly:
So this is a “tools for the job” question, I would always start from Python;
from datetime import datetime
date_format = "%d/%m/%Y"
a = datetime.strptime('31/05/2005', date_format)
b = datetime.now()
delta = b - a
print(delta.days)
The benefits of using this over bash;
The code is readable, i.e. you can immediately see what it’s doing
Changing the date format is trivial (to include time or US format)
Python is somewhat faster than bash (!)
If you really need to use bash for other stuff, then just write a 10-line Python script (as above) then call it from bash, for example;
from sys import argv
from datetime import datetime
if len (argv) < 2:
print (f'usage: {argv[0]} <date> [<format>]')
exit
date_format = "%d/%m/%Y" if len(argv) < 3 else argv[2]
a = datetime.strptime(argv[1], date_format)
b = datetime.now()
delta = b - a
print(delta.days)
If you call it “date.py” then do “chmod +x date.py”;
If you really must do it in bash, then revert to an expert like Gemini …
#!/bin/bash
# Check if a date is provided
if [ -z "$1" ]; then
echo "Usage: $0 <DD/MM/YYYY>"
exit 1
fi
provided_date_str="$1"
# Set locale to en_GB.UTF-8 to ensure date command interprets DD/MM/YYYY correctly
# This is a good practice, though 'date -d' is often flexible.
export LC_ALL="en_GB.UTF-8"
# Validate the provided date format and attempt to convert to YYYY-MM-DD for date -d
# We'll use awk to reformat the date string
reformatted_date=$(echo "$provided_date_str" | awk -F'/' '{print $3"-"$2"-"$1}')
# Check if the reformatted date is valid
if ! date -d "$reformatted_date" &> /dev/null; then
echo "Error: Invalid date format or date. Please use DD/MM/YYYY, e.g., 25/12/2024."
exit 1
fi
# Convert provided date to Unix timestamp
provided_date_timestamp=$(date -d "$reformatted_date" +%s)
# Get current date as Unix timestamp
current_date_timestamp=$(date +%s)
# Calculate the difference in seconds
difference_in_seconds=$(( current_date_timestamp - provided_date_timestamp ))
# Convert seconds to days
# Integer division will naturally floor the result, giving you whole days
difference_in_days=$(( difference_in_seconds / (60 * 60 * 24) ))
echo "Number of days from $provided_date_str until the current date: $difference_in_days"
I think the key takeaway here is that if you set the LC_ALL environment variable correctly then bash’s “date” command should work with the date formats you’re expecting
As always I am grateful for the effort that you have put in to your reply!
And, as is often the case, I struggle to follow what appear to the novice as really complicated solutions.
Python commands (like any language) are easy to follow only if one is familiar with the language. I did make a start on learning Python some years ago it but fell by the wayside as BASH felt more straightforward to me. Horses for courses, I guess.
I can’t find an environment variable LC_ALL that I could alter, and the Locale variables appear to be correct, but just not working.
My application is a simple start-up script to read the date of my last backup and tell me (by espeak) how many days it’s been since then. All I have to do is ensure that the saved date is in USA format and Bob’s-your-uncle. No extra lines of code.
I think I will stick with the easy option, but am grateful for the detailed response.
It’s already outputting that UK format for the plain date command - just as it’s supposed to. My problem is when I specify a date it will only accept USA format. e.g.:
keith@E5570:~$ date -d 5/31/2005
Tue 31 May 00:00:00 BST 2005
keith@E5570:~$ date -d 31/5/2005
date: invalid date ‘31/5/2005’
keith@E5570:~$
But it’s not worth worrying about - I just wondered if I was doing something incorrectly. But it looks like there is a bug in the date command.
Yeah it’s not a bug, I think it’s what they call a ‘feature’. To avoid any confusion, if you’re going to use “/” for input, it’s always m/d/y. Then for output it will use the locale settings. What you it can do;
$ env LC_ALL="en_GB.UTF-8" date -d "31-May-2005"
Tue 31 May 00:00:00 BST 2005