Date Parsing and Arithmetic on macOS
I recently wrote a shell script that required both date parsing and date arithmetic. The pertinent bits for this post are that the script:
- Accepted a date as a parameter
- Accepted a number of days as a parameter
- Iterated through the dates to generate specific strings in “year-month-day” format, e.g., “20230225” for February 25, 2023
Seemed simple enough. A little googling and some experimentation gave me this snippet that worked on Linux:
for ((i = 0; i < $2; i++)); do
current=$(date +%Y%m%d -d "$1 + $i days")
echo $current
done
Running this on Linux, with a start date of February 25, 2023, and a run of 10 days, produced this:
$ ./dates.sh 20230225 10
20230225
20230226
20230227
20230228
20230301
20230302
20230303
20230304
20230305
20230306
Running this on the target platform, macOS, produced this:
$ ./dates.sh 20230225 10
date: illegal time format
usage: date [-jnRu] [-r seconds|file] [-v[+|-]val[ymwdHMS]]
[-I[date | hours | minutes | seconds]]
[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
[repeated 10 times]
OK, so date
differs between the platforms. So I typed man date
, giggled a little, discovered the -j
, -f
, and -v
flags, and put them together like this:
current=$(date -jf '%Y%m%d' "$1" -v +"$i"d '+%Y%m%d')
Running that gave me this:
$ ./dates.sh 10
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
Sat Feb 25 11:39:56 EST 2023
So I googled and I fussed with the -v
format and the output format and got frustrated. Just when I was about to rewrite it all in Python, which I know about as well as I know Italian, I tried putting the -v
flag first:
#!/bin/bash
for ((i = 0; i < $2; i++)); do
current=$(date -v +"$i"d -jf '%Y%m%d' "$1" '+%Y%m%d')
echo $current
done
And that gave me this:
$ ./dates.sh 20230225 10
20230225
20230226
20230227
20230228
20230301
20230302
20230303
20230304
20230305
20230306
Order matters, I guess, with the macOS date
command. Increment, parse, output. YMMV.