On 13/05/2022 20:10, t0th wrote:
Man page of date command should make explicit that -d and -r options are
mutually exclusive.
Right. More accurately, we might have a sentence to say that:
"All options to specify the date to display are mutually exclusive.
I.e.: --date, --file, --reference, --resolution".
However...
date -d -3 minutes -r tmp.txt "+%Y%m%d_%H%M"
date: the options to specify dates for printing are mutually exclusive
As you've seen, one might expect to be able to combine, as -d can be relative.
So theoretically we could support this (with the attached),
to honor the relative adjustment, but give precedence to a non relative date.
$ src/date -r src/ls.c -d '-3 minutes'
Fri 15 Apr 2022 16:30:53 IST
$ src/date -r src/ls.c -d '1/1/2022'
Sat 01 Jan 2022 00:00:00 GMT
In fact touch(1) behaves like this, which suggests date(1) should also.
From the info docs for the touch --reference option:
"--reference
Use the times of the reference FILE instead of the current time.
If this option is combined with the --date=TIME
(-d TIME) option, the reference FILES's time is
the origin for any relative TIMEs given, but is otherwise ignored."
BTW, one might also expect that multiple -d options might combine like this,
however currently we silently ignore multiple -d (or -s) options.
The attached also at least warns about this with --debug:
$ date --debug -d '15/4/2022' -d '-3 minutes'
date: discarding previous -d: ‘15/4/2022’
date: parsed relative part: -3 minutes
...
cheers,
Pádraig
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 7bca37b71..ae6ec4def 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -16058,7 +16058,8 @@ is not set. @xref{TZ Variable,, Specifying the Time Zone with
@cindex formatting times
If given an argument that starts with a @samp{+}, @command{date} prints the
current date and time (or the date and time specified by the
-@option{--date} option, see below) in the format defined by that argument,
+@option{--date}, @option{--file}, or @option{--reference} options, see below)
+in the format defined by that argument,
which is similar to that of the @code{strftime} function. Except for
conversion specifiers, which start with @samp{%}, characters in the
format string are printed unchanged. The conversion specifiers are
@@ -16502,6 +16503,9 @@ for the @option{--date} (@option{-d}) and @option{--file}
@opindex --reference
Display the date and time of the last modification of @var{file},
instead of the current date and time.
+If this option is combined with the @option{--date} or @option{--file}
+options, the reference @var{file}'s time is
+the origin for any relative @var{time}s given, but is otherwise ignored.
@item --resolution
@opindex --resolution
diff --git a/src/date.c b/src/date.c
index 9a282e2f5..de94136fe 100644
--- a/src/date.c
+++ b/src/date.c
@@ -420,6 +420,8 @@ main (int argc, char **argv)
switch (optc)
{
case 'd':
+ if (datestr && (parse_datetime_flags & PARSE_DATETIME_DEBUG))
+ error (0, 0, _("discarding previous -d: %s"), quote (datestr));
datestr = optarg;
break;
case DEBUG_DATE_PARSING_OPTION:
@@ -469,6 +471,8 @@ main (int argc, char **argv)
new_format = rfc_email_format;
break;
case 's':
+ if (set_datestr && (parse_datetime_flags & PARSE_DATETIME_DEBUG))
+ error (0, 0, _("discarding previous -s: %s"), quote (set_datestr));
set_datestr = optarg;
set_date = true;
break;
@@ -494,8 +498,7 @@ main (int argc, char **argv)
}
}
- int option_specified_date = (!!datestr + !!batch_file + !!reference
- + get_resolution);
+ int option_specified_date = (!!datestr + !!batch_file + get_resolution);
if (option_specified_date > 1)
{
@@ -511,6 +514,9 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
+ /* Use as base for other "relative" specified dates. */
+ option_specified_date += !!reference;
+
if (optind < argc)
{
if (optind + 1 < argc)
@@ -597,7 +603,8 @@ main (int argc, char **argv)
die (EXIT_FAILURE, errno, "%s", quotef (reference));
when = get_stat_mtime (&refstats);
}
- else if (get_resolution)
+
+ if (get_resolution)
{
long int res = gettime_res ();
when.tv_sec = res / TIMESPEC_HZ;
@@ -605,9 +612,10 @@ main (int argc, char **argv)
}
else
{
+ struct timespec *now = reference ? &when : NULL;
if (set_datestr)
datestr = set_datestr;
- valid_date = parse_datetime2 (&when, datestr, NULL,
+ valid_date = parse_datetime2 (&when, datestr, now,
parse_datetime_flags,
tz, tzstring);
}