bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-gnulib] getdate.y question


From: Derek Robert Price
Subject: Re: [Bug-gnulib] getdate.y question
Date: Thu, 28 Oct 2004 14:38:03 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040616

Paul Eggert wrote:

>"Jim.Hyslop" <address@hidden> writes:
>
>  
>
>>Refactor the functionality out of mktime into a separate function,
>>say mktime_checked, which accepts an additional boolean parameter,
>>say allow_overflow.
>>    
>>
>
>There's no need for any of this.  All you have to do is check that the
>output of mktime (the struct tm, that is) is the same as the input.
>
>The only problem comes up near the boundary conditions like 2038,
>where the time zone of the time stamp may differ from your time zone.
>  
>

I finally got around to taking a shot at this.  The original problem is
that getdate is currently not rejecting dates like January 40th, 2004,
but rather converting them.  In this example it currently returns
February 9th, 2004.

Paul, you were right about the basic patch being pretty simple, but I
have no idea if I approached the boundry conditions correctly (in fact,
I haven't special-cased them - I started to but discovered that the
patch was already doing what I wanted as far as I could tell).  At the
very least, this patch causes getdate to reject improper dates that are
not near the boundries and is an improvement over what getdate.y is
currently doing and I think it should definitely be applied.

    * lib/getdate.y (not_equal_tm): New function.
    (getdate): Verify that mktime() did not need to "repair" the date.


The attached script will demonstrate that getdate works when it can find
an executable named "getdate".  If you'll note the final six tests, I
failed to find a boundry condition near 1970-01-01, but it _does_ still
appear to be rejecting dates as it is supposed to.  The fact that I
couldn't find the boundry led me to believe that there is something here
that I do not understand, however.

Input:
1969-12-32 2:00:00 UTC
1970-01-01 2:00:00 UTC
1969-12-32 2:00:00 +0400
1970-01-01 2:00:00 +0400
1969-12-32 2:00:00 -0400
1970-01-01 2:00:00 -0400

Output:
> Bad format - couldn't convert.
> 1970-01-01 02:00:00.000000000
> Bad format - couldn't convert.
> 1969-12-31 22:00:00.000000000
> Bad format - couldn't convert.
> 1970-01-01 06:00:00.000000000


Again, the attached patch should almost certainly be applied, but if
someone could explain the boundry conditions to me more clearly and it
turns out they are not being handled, I can take a shot at handling them
as well, in a second patch.

Feel free to add the attached test script to the GNULIB test suite too,
if you like.


The (separate) CVS test suite, which makes fairly heavy use of getdate,
passes using the current getdate.y from GNULIB with this patch applied,
meaning that at least as far as the dates in old CVS test suite are
concerned, the new getdate behavior matches the old.

Cheers,

Derek

-- 
                *8^)

Email: address@hidden

Get CVS support at <http://ximbiot.com>!

Index: lib/getdate.y
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getdate.y,v
retrieving revision 1.85
diff -u -p -r1.85 getdate.y
--- lib/getdate.y       25 Oct 2004 05:50:16 -0000      1.85
+++ lib/getdate.y       28 Oct 2004 18:17:15 -0000
@@ -990,6 +990,29 @@ yyerror (parser_control *pc ATTRIBUTE_UN
   return 0;
 }
 
+
+
+/* Report if two struct tms are the same.  Ignores tm_wday and tm_yday since
+ * mktime() can set them harmlessly as far as get_date() is concerned.  This
+ * function is used to find if mktime() normalized a date, for instance
+ * converting January 40th to February 9th, which mktime() is perfectly happy
+ * to do.
+ *
+ * This was originally copied from GNULIB's lib/mktime.c and modified.
+ */
+static bool
+not_equal_tm (const struct tm *a, const struct tm *b)
+{
+  return (a->tm_sec ^ b->tm_sec)
+        | (a->tm_min ^ b->tm_min)
+        | (a->tm_hour ^ b->tm_hour)
+        | (a->tm_mday ^ b->tm_mday)
+        | (a->tm_mon ^ b->tm_mon)
+        | (a->tm_year ^ b->tm_year);
+}
+
+
+
 /* Parse a date/time string, storing the resulting time value into *RESULT.
    The string itself is pointed to by P.  Return true if successful.
    P can be an incomplete or relative time specification; if so, use
@@ -1181,6 +1204,17 @@ get_date (struct timespec *result, char 
       if (Start == (time_t) -1)
        return false;
     }
+  else if (!pc.rels_seen && not_equal_tm (&tm0, &tm))
+    {
+      /* If our time struct going in is different than the one coming out, then
+       * mktime() found cause to normalize it.  This means the date was
+       * something like "January 40th, 2004", which would cause mktime to "fix"
+       * the tm, returning "February 9th, 2004".
+       *
+       * The getdate() charter says to reject these sorts of dates.
+       */
+      return false;
+    }
 
   if (pc.days_seen && ! pc.dates_seen)
     {

Attachment: test-getdate.sh
Description: Bourne shell script

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]