On 05.02.18 09:39, Greg Wooledge wrote: > On Sun, Feb 04, 2018 at 04:04:34PM +0100, Nicolas George wrote: > > All you describe is convenience for programmatic use. As I explained, > > this parser is meant for interactive use. > > What on EARTH made you think THAT?
The fuzzy grammar of the date string makes programmatic use a bit empirical, I must admit. > I promise you, people ARE using date -d '...' in shell scripts. > LOTS of people. Hell, I've done it.(*) A data point: I have been using "date" for a good 30 years, on hp-ux, SunOS, Solaris, and now linux - pretty much _exclusively_ in scripts, even with -d. An example still in use even scripts the "human readable" input: #!/bin/bash [ `date '+%H'` -lt 4 ] && day="yesterday" || day="today" d="`date -d $day '+%a %b %_d'`" ... echo "`date -d $day '+%a %b %_d'`" $n >> ~/fetchmail_traffic If a new formal grammar largely consistent with the "mostly free format human readable date string" were defined in the manpage, then that could be a step forward. > If I'm a human working in an interactive shell, and I want to see "the > date of the Sunday that occurred in the previous week", I will simply > run cal(1) instead. (Or for that specific example on this specific > day, "cal 1 2018" or even "cal 2018".) It's a lot easier than trying > to guess which recipe you can put into date -d to get the same result. Yes, cal is less effort. I use date interactively only when developing a script. For me, the "mostly free format human readable date string" is irrelevant, as it merely serves as an undocumented grammar. > > (*) One specific shell script use case was "Get the last date of a given > month." Now, obviously you can just set up an array of hard-coded month > ending dates, and then write a function to determine whether the current > year is a leap year for the February case. But if you want to do it with > GNU date -d, then you have to guess a magic incantation that actually > works. Usually by trial and error. > > Anyway, here's what I came up with: > > lastday() { > date +%Y-%m-%d -d "$1 1 day ago + 1 month" > } ... > How does it work? Who knows! That's quite straightforward, I submit. Omitting the "+ 1 month", your expression is equivalent to: (with $1 substituted for example 1) $ date +%Y-%m-%d -d "2016-03-01 - 1 day" 2016-02-29 which simply steps backward from first of the month to last of the previous. Then stepping forward a month merely avoids the need to input first of next month for last of this one. > But it seems to work. It correctly > handles the oddball corner cases like Feb 2100 (which is not a leap > year), and the March-that-follows-a-leap-day as well as the > March-that-does-not-follow-a-leap-day. So that is where I left it. And for the far past, cal is superior; compare: $ cal -3 9 1752 August 1752 September 1752 October 1752 Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa 1 1 2 14 15 16 1 2 3 4 5 6 7 2 3 4 5 6 7 8 17 18 19 20 21 22 23 8 9 10 11 12 13 14 9 10 11 12 13 14 15 24 25 26 27 28 29 30 15 16 17 18 19 20 21 16 17 18 19 20 21 22 22 23 24 25 26 27 28 23 24 25 26 27 28 29 29 30 31 30 31 with $ date +%Y-%m-%d -d "1752-10-01 - 1 day" date: invalid date `1752-10-01 - 1 day' Cal delivers the goods, but date lacks the time travelling range. Erik