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

Reply via email to