Hello, I fixed the regression you found and added some new tests.
$ ./date -d "fri" +%a.%F ven.2009-05-01 $ date -d "fri" +%a.%F ven.2009-05-01 and: $ ./date -d "next fri" +%a.%F ven.2009-05-08 $ date -d "next fri" +%a.%F ven.2009-05-01 Regards, Giuseppe
>From 0e1af7775a82aed00331a535ddadee2753d12e5e Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano <gscriv...@gnu.org> Date: Fri, 1 May 2009 15:44:30 +0200 Subject: [PATCH] =?utf-8?q?*=20lib/getdate.y=20(get=5Fdate):=20Correct=20the=20calculation=20of=20tm=5Fmday=20so =20that=20e.g.,=20"next=20tues"=20(when=20run=20on=20a=20tuesday)=20results=20in=20a=20date =20that=20is=20one=20week=20in=20the=20future,=20and=20not=20today's=20date. =20I.e.,=20add=20a=20week=20when=20the=20wday=20is=20the=20same=20as=20the=20current=20one. =20Reported=20by=20Tom=20Broadhurst=20in=20http://savannah.gnu.org/bugs/=3F25406, =20and=20earlier=20by=20Martin=20Bernreuther=20and=20Jan=20Min=C3=A1=C5=99. =20*=20tests/test-getdate.c=20(main):=20Check=20that=20"next=20DAY"=20is=20always=20in =20the=20future.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit --- lib/getdate.y | 10 +++++--- tests/test-getdate.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/lib/getdate.y b/lib/getdate.y index 877b264..786e873 100644 --- a/lib/getdate.y +++ b/lib/getdate.y @@ -1,7 +1,7 @@ %{ /* Parse a string into an internal time stamp. - Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -404,12 +404,12 @@ zone: day: tDAY { - pc->day_ordinal = 1; + pc->day_ordinal = 0; pc->day_number = $1; } | tDAY ',' { - pc->day_ordinal = 1; + pc->day_ordinal = 0; pc->day_number = $1; } | tORDINAL tDAY @@ -1435,7 +1435,9 @@ get_date (struct timespec *result, char const *p, struct timespec const *now) if (pc.days_seen && ! pc.dates_seen) { tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7 - + 7 * (pc.day_ordinal - (0 < pc.day_ordinal))); + + 7 * (pc.day_ordinal + - (0 < pc.day_ordinal + && tm.tm_wday != pc.day_number))); tm.tm_isdst = -1; Start = mktime (&tm); if (Start == (time_t) -1) diff --git a/tests/test-getdate.c b/tests/test-getdate.c index 7dfb09e..73c3ad1 100644 --- a/tests/test-getdate.c +++ b/tests/test-getdate.c @@ -48,6 +48,22 @@ #define LOG(str, now, res) (void) 0 #endif +static const char* const day_table[] = +{ + "SUNDAY", + "MONDAY", + "TUESDAY", + "TUES", + "WEDNESDAY", + "WEDNES", + "THURSDAY", + "THUR", + "THURS", + "FRIDAY", + "SATURDAY", + NULL +}; + int main (int argc, char **argv) { @@ -55,6 +71,7 @@ main (int argc, char **argv) struct timespec result2; struct timespec now; const char *p; + int i; set_program_name (argv[0]); @@ -211,5 +228,42 @@ main (int argc, char **argv) ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); + /* Check that every 'last/next DAY' is in the past/future. */ + for (i = 0; day_table[i]; i++) + { + char tmp[32]; + sprintf (tmp, "NEXT %s", day_table[i]); + now.tv_sec = 4711; + now.tv_nsec = 1267; + ASSERT (get_date (&result, tmp, &now)); + LOG (tmp, now, result); + ASSERT (result.tv_sec > now.tv_sec + && result.tv_nsec == 0); + + sprintf (tmp, "LAST %s", day_table[i]); + now.tv_sec = 4711; + now.tv_nsec = 1267; + ASSERT (get_date (&result, tmp, &now)); + LOG (tmp, now, result); + ASSERT (result.tv_sec < now.tv_sec + && result.tv_nsec == 0); + } + + p = "THURSDAY UTC+00"; /* The epoch was on Thursday. */ + now.tv_sec = 0; + now.tv_nsec = 0; + ASSERT (get_date (&result, p, &now)); + LOG (p, now, result); + ASSERT (result.tv_sec == now.tv_sec + && result.tv_nsec == now.tv_nsec); + + p = "FRIDAY UTC+00"; + now.tv_sec = 0; + now.tv_nsec = 0; + ASSERT (get_date (&result, p, &now)); + LOG (p, now, result); + ASSERT (result.tv_sec >= now.tv_sec + && result.tv_nsec == now.tv_nsec); + return 0; } -- 1.6.2.1
Jim Meyering <j...@meyering.net> writes: > Giuseppe Scrivano wrote: >> This patch includes all your suggestions and new tests for >> test-getdate.c. > > Thanks for the quick test addition! > I want the summary line to start with "getdate: " > and do be "high-level descriptive" so I moved your > "add a week..." sentence into the body of the log. > Also, I kept the TAB-oriented indentation and made > Bruno's simplification (Thanks, Bruno!). > > Regarding the test, I added a "const" and tweaked formatting > so the continued expression starts with "&&" rather than > leaving the operator at the end of the preceding line. > That is the prevailing and recommended style. > > However, there is a problem. > With this change, today (a Friday), ./date -d fri > prints the date for a week from today. > Without the patch, it prints today's date. > That is a regression, and shows that we'll need > several more tests. > > If you make further changes, please use the following > as a basis, so I don't have to change your spaces to TABs > again or to adjust the content or formatting of the commit log. > > > From 664db25a03246f510793d74fce674b68f32d1dc3 Mon Sep 17 00:00:00 2001 > From: Giuseppe Scrivano <gscriv...@gnu.org> > Date: Fri, 1 May 2009 09:23:20 +0200 > Subject: [PATCH] getdate: correctly interpret "next monday" when run on a > Monday > MIME-Version: 1.0 > Content-Type: text/plain; charset=utf-8 > Content-Transfer-Encoding: 8bit > > * lib/getdate.y (get_date): Correct the calculation of tm_mday so > that e.g., "next tues" (when run on a tuesday) results in a date > that is one week in the future, and not today's date. > I.e., add a week when the wday is the same as the current one. > Reported by Tom Broadhurst in http://savannah.gnu.org/bugs/?25406, > and earlier by Martin Bernreuther and Jan Minář. > * tests/test-getdate.c (main): Check that "next DAY" is always in > the future. > --- > lib/getdate.y | 6 ++++-- > tests/test-getdate.c | 30 ++++++++++++++++++++++++++++++ > 2 files changed, 34 insertions(+), 2 deletions(-) > > diff --git a/lib/getdate.y b/lib/getdate.y > index 877b264..48bf391 100644 > --- a/lib/getdate.y > +++ b/lib/getdate.y > @@ -1,7 +1,7 @@ > %{ > /* Parse a string into an internal time stamp. > > - Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008 > + Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 > Free Software Foundation, Inc. > > This program is free software: you can redistribute it and/or modify > @@ -1435,7 +1435,9 @@ get_date (struct timespec *result, char const *p, > struct timespec const *now) > if (pc.days_seen && ! pc.dates_seen) > { > tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7 > - + 7 * (pc.day_ordinal - (0 < pc.day_ordinal))); > + + 7 * (pc.day_ordinal > + - (0 < pc.day_ordinal > + && tm.tm_wday != pc.day_number))); > tm.tm_isdst = -1; > Start = mktime (&tm); > if (Start == (time_t) -1) > diff --git a/tests/test-getdate.c b/tests/test-getdate.c > index 7dfb09e..9cee073 100644 > --- a/tests/test-getdate.c > +++ b/tests/test-getdate.c > @@ -48,6 +48,22 @@ > #define LOG(str, now, res) (void) 0 > #endif > > +static const char* const day_table[] = > +{ > + "SUNDAY", > + "MONDAY", > + "TUESDAY", > + "TUES", > + "WEDNESDAY", > + "WEDNES", > + "THURSDAY", > + "THUR", > + "THURS", > + "FRIDAY", > + "SATURDAY", > + NULL > +}; > + > int > main (int argc, char **argv) > { > @@ -55,6 +71,7 @@ main (int argc, char **argv) > struct timespec result2; > struct timespec now; > const char *p; > + int i; > > set_program_name (argv[0]); > > @@ -211,5 +228,18 @@ main (int argc, char **argv) > ASSERT (result.tv_sec == result2.tv_sec > && result.tv_nsec == result2.tv_nsec); > > + /* Check that every 'next DAY' is in the future. */ > + for (i = 0; day_table[i]; i++) > + { > + char tmp[32]; > + sprintf (tmp, "NEXT %s", day_table[i]); > + now.tv_sec = 4711; > + now.tv_nsec = 1267; > + ASSERT (get_date (&result, tmp, &now)); > + LOG (tmp, now, result); > + ASSERT (result.tv_sec > now.tv_sec > + && result.tv_nsec == 0); > + } > + > return 0; > } > -- > 1.6.3.rc3.212.g8c698