Thanks Bernhard,
On 2019-04-15 2:14 p.m., Bernhard Voelker wrote:
I can easily reproduce here on my regular openSUSE:Tumbleweed from latest git:
$ src/date --debug '+%-Y' -d '- 2010 years'
[....]
date: error: adding relative date resulted in an invalid date: '(Y-M-D)
0009-04-15 22:10:37'
This makes it easy to pinpoint (hooray for "--debug" :) ).
This error is given if gnulib's "mktime_z" fails
to convert the adjusted "struct tm" to "time_t"
(adjusted because its tm_year was decremented by 2010).
https://opengrok.housegordon.com/source/xref/gnulib/lib/parse-datetime.y#2177
To see if this is glibc issue, or perhaps an gnulib/mktime_z wrapper
issue, can you (and/or others) try the attached C program?
It calls time(2)+localtime(3)+mktime(3) to emulate the date adjustment.
Because the adjustment is to year 9 (about 1961 years before epoch),
the time_t value is negative. perhaps that's the issue? or perhaps
combined with a specific timezone it becomes problematic?
On my system it gives:
----
$ gcc -o inv-year inv-year.c
$ ./inv-year
time() = 1555361050
localtime() = 2019-04-15 14:44:10
(mday=15 wday=1, isdst=1)
struct tm (after adjustment) = 0009-04-15 14:44:10
(mday=15 wday=1, isdst=1)
mktime() after date adjustment = -61874070118
----
regards,
- assaf
/* A test program to help with https://bugs.gnu.org/35289#28
compile with:
gcc -o inv-year inv-year.c
written by Assaf Gordon (assafgor...@gmail.com).
placed under public domain.
*/
#include <time.h>
#include <stdio.h>
#include <err.h>
#include <string.h>
int main()
{
time_t now = time(NULL);
if ( now == ((time_t) -1))
err(1, "time() failed");
printf("time() = %ld\n", (signed long)now);
struct tm *a = localtime(&now);
if (!a)
err(1, "localtime(now) failed");
printf("localtime() = %04d-%02d-%02d %02d:%02d:%02d\n"
" (mday=%d wday=%d, isdst=%d)\n",
a->tm_year+1900,a->tm_mon+1,a->tm_mday,
a->tm_hour, a->tm_min, a->tm_sec,
a->tm_mday, a->tm_wday, a->tm_isdst);
struct tm b;
memcpy (&b, a, sizeof b);
/******************************************************
* Test date adjustment by changing 'b' members
******************************************************/
b.tm_year -= 2010;
printf("struct tm (after adjustment) = %04d-%02d-%02d %02d:%02d:%02d\n"
" (mday=%d wday=%d, isdst=%d)\n",
b.tm_year+1900,b.tm_mon+1,b.tm_mday,
b.tm_hour, b.tm_min, b.tm_sec,
b.tm_mday, b.tm_wday, b.tm_isdst);
time_t notnow = mktime (&b);
if ( notnow == ((time_t) -1) )
err(1, "mktime() failed");
printf("mktime() after date adjustment = %ld\n", (signed long)notnow);
return 0;
}