Subject: Re: bug#30102: date -d 'next tuesday, 2 years ago' # Is something like that supported?

From: Assaf Gordon <[email-masked]>
Date: Sun, 14 Jan 2018 03:50:07 -0700

tag 30102 notabug
close 30102
stop

Hello,

On 2018-01-13 05:03 PM, [email-masked] wrote:
> $ date --version
> date (GNU coreutils) 8.27

In version 8.27 the date command has an additional option called 
"--debug" which can help in understanding the date parsing.
I will use it in the output below.

> $ info date -n 'Date input formats' |grep 'next tue'
> * Relative items in date strings:: next tuesday, 2 years ago.

Date does accept "2 years ago next Tuesday".
However, it first calculates "next Tuesday" (which as of this writing is 
2018-Jan-16), and then subtracts two years, giving "Sat, Jan 16th, 
2016". Not sure if that is what you wanted.

===
$ date --debug -d 'next tuesday 2 years ago'
date: parsed day part: next/first Tue (day ordinal=1 number=2)
date: parsed relative part: -2 year(s)
date: input timezone: system default
date: warning: using midnight as starting time: 00:00:00
date: new start date: 'next/first Tue' is '(Y-M-D) 2018-01-16 00:00:00'
date: starting date/time: '(Y-M-D) 2018-01-16 00:00:00'
date: warning: when adding relative months/years, it is recommended to 
specify the 15th of the months
date: after date adjustment (-2 years, +0 months, +0 days),
date:     new date/time = '(Y-M-D) 2016-01-16 00:00:00'
date: '(Y-M-D) 2016-01-16 00:00:00' = 1452927600 epoch-seconds
date: timezone: system default
date: final: 1452927600.000000000 (epoch-seconds)
date: final: (Y-M-D) 2016-01-16 07:00:00 (UTC)
date: final: (Y-M-D) 2016-01-16 00:00:00 (UTC-07)
Sat Jan 16 00:00:00 MST 2016
===

> My goal is to find for example the date of the first Saturday after 1/7/2018
> with a single date command.

Of the top of my head I can't think of a single command that would work,
because 'date' ignores "next tuesday" when given an explicit date, as 
shown below (notice the warning):

===
date --debug -d "2018-01-07 next tuesday"
date: parsed date part: (Y-M-D) 2018-01-07
date: parsed day part: next/first Tue (day ordinal=1 number=2)
date: input timezone: system default
date: warning: using midnight as starting time: 00:00:00
date: warning: day (next/first Tue) ignored when explicit dates are given
date: starting date/time: '(Y-M-D) 2018-01-07 00:00:00'
date: '(Y-M-D) 2018-01-07 00:00:00' = 1515308400 epoch-seconds
date: timezone: system default
date: final: 1515308400.000000000 (epoch-seconds)
date: final: (Y-M-D) 2018-01-07 07:00:00 (UTC)
date: final: (Y-M-D) 2018-01-07 00:00:00 (UTC-07)
Sun Jan  7 00:00:00 MST 2018
===

However, it can be done with two commands:
first, find the day-of-week (DOW) of the desired date (2018-Jan-7 is 
Sunday). I will use the "%w" format (see 'date --help'):
      %w   day of week (0..6); 0 is Sunday
Then, calculate how many days we need to add to get to saturday (6 
days), and show the date of '2018-Jan-7 + 6 days':

===
$ FROM="2018-01-07"
$ DOW=$(date -d "$FROM" +%w)
$ ADDDAYS=$((6-DOW))
$ date -d "$FROM + $ADDDAYS days"
Sat Jan 13 00:00:00 MST 2018
===

Lastly,
You wrote "after 1/7/2018" so I assume you wanted a specific date.
But if you just want "next saturday" from today (or from last week), 
then date 'just works':

===
$ date
Sun Jan 14 03:48:03 MST 2018

$ date -d 'next saturday'
Sat Jan 20 00:00:00 MST 2018

$ date -d 'last week next saturday'
Sat Jan 13 00:00:00 MST 2018
===

I'm marking this as "not a bug" and closing it because it is a question 
and not a bug - but general discussion is very welcomed to continue,
simply by replying to this thread.

regards,
  - assaf