Issue
Just now ("Sun Jun 9 17:19:24 MDT 2013"), I ran this command:
> date -d "first Sunday next month"
Tue Jul 9 00:00:00 MDT 2013
which is neither a Sunday, and isn't even the first Tuesday of next month:
How is date -d interpreting my input?
Is there a verbose option to date (or even "date -d") that shows how my input is interpreted? It's not -v, and "man date" doesn't show a verbose option.
I realize there's probably some library handling "date -d". Where can I find that library and its documentation, limitations, etc?
I realize no program can handle every possible format, but it's unnerving to see "date -d" give the wrong answer. I'd have much preferred "date: can not parse 'first Sunday next month'" to the wrong answer.
EDIT: running this on fedora 11 core:
> date --version
date (GNU coreutils) 7.2
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Solution
- How is date -d interpreting my input?
Via this Bison grammar that's part of Gnulib, on which date
(and indeed much of the coreutils package) depends. My days of writing grammars are long gone, but the relative date/time parsing "fun" seems to start around line 892.
- Is there a verbose option to date (or even "date -d") that shows how my input is interpreted?
The current version of GNU date as I write this (v8.28) does have a debug mode:
$ date --debug -d "first Sunday next month"
date: parsed day part: next/first Sun (day ordinal=1 number=0)
date: parsed relative part: +1 month(s)
date: input timezone: system default
date: warning: using midnight as starting time: 00:00:00
date: new start date: 'next/first Sun' is '(Y-M-D) 2019-02-03 00:00:00'
date: starting date/time: '(Y-M-D) 2019-02-03 00:00:00'
date: warning: when adding relative months/years, it is recommended to specify the 15th of the months
date: after date adjustment (+0 years, +1 months, +0 days),
date: new date/time = '(Y-M-D) 2019-03-03 00:00:00'
date: '(Y-M-D) 2019-03-03 00:00:00' = 1551542400 epoch-seconds
date: timezone: system default
date: final: 1551542400.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-03-02 16:00:00 (UTC)
date: final: (Y-M-D) 2019-03-03 00:00:00 (UTC+08)
Sun Mar 3 00:00:00 +08 2019
As you can see, it went left-to-right; * "first Sunday" resolves forward to the first Sunday of Feb 2019 (2019-Feb-03), then * "next month" adds one month (2019-Mar-03), which just happens to be a Sunday too, since it's not a leap year.
- I realize there's probably some library handling "date -d". Where can I find that library and its documentation, limitations, etc?
Gnulib, as mentioned above. Also, the Date input formats section of the coreutils manual is worth reading in detail.
- I realize no program can handle every possible format, but it's unnerving to see "date -d" give the wrong answer. I'd have much preferred "date: can not parse 'first Sunday next month'" to the wrong answer.
I'm sure the authors of the parse_datetime
routine would agree. Sadly, your date phrasing seems like it just happens to match some grouping of the existing grammar rules, so date
dutifully does the necessary calculation...and comes up with the wrong answer.
Perhaps a polite bug report to the Gnulib bugs mailing list ([email protected]) might set some gears turning.
Oh, and you probably already figured it out, but date -d "first Sunday"
gets you the right result...as long as you're past the current month's first Sunday. :)
Answered By - Adrian