[Gnucash-changes] fix the documentation surrounding the gnc_iso8601_to_timespec routine().

Linas Vepstas linas at cvs.gnucash.org
Sun May 2 18:04:07 EDT 2004


Log Message:
-----------
fix the documentation surrounding the gnc_iso8601_to_timespec routine().

Modified Files:
--------------
    gnucash/src/engine:
        gnc-date.c
        gnc-date.h

Revision Data
-------------
Index: gnc-date.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-date.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -Lsrc/engine/gnc-date.h -Lsrc/engine/gnc-date.h -u -r1.8 -r1.9
--- src/engine/gnc-date.h
+++ src/engine/gnc-date.h
@@ -34,7 +34,22 @@
     applications, besides just GnuCash, use this file.  In particular,
     GnoTime (gttr.sourcefore.net) uses this file, and this file is 
     formally a part of QOF (qof.sourceforge.net).
-    *
+
+    An important note about time-keeping:  The general goal of any 
+    program that works with numeric time values SHOULD BE to always
+    stores and use UNIVERSAL TIME internally.  Universal time is the
+    'one true time' that is independent of one's location on planet
+    Earth.  It is measured in seconds from midnight January 1, 1970
+    in localtime-Grenwich (GMT).  If one wants to display the local
+    time, then the display-print routine should make all final 
+    tweaks to print the local time.   The local time *must not* be
+    kept as a numeric value anywhere in the program.   If one wants
+    to parse a user's input string as if it were local time, then
+    the output of the parse routine MUST BE universal time.  
+    A sane program must never ever store (to file or db) a time 
+    that is not Universal Time.  Break these rules, and you will 
+    rue the day...
+
     @author Copyright (C) 1997 Robin D. Clark <rclark at cs.hmc.edu> 
     @author Copyright (C) 1998-2001,2003 Linas Vepstas <linas at linas.org>
 */
@@ -173,25 +188,40 @@
 /** Same as gnc_dmy2timespec, but last second of the day */
 Timespec gnc_dmy2timespec_end (int day, int month, int year);
 
-/** The gnc_iso8601_to_timespec_local() routine converts an ISO-8601 style 
- *    date/time string to Timespec.
- *    For example: 1998-07-17 11:00:00.68-05 
- *    is 680 milliseconds after 11 o'clock, central daylight time 
- *    \return The time in local time.*/
-Timespec gnc_iso8601_to_timespec_local(const char *);
-
 /** The gnc_iso8601_to_timespec_gmt() routine converts an ISO-8601 style 
- *    date/time string to Timespec.
- *    For example: 1998-07-17 11:00:00.68-05 
+ *    date/time string to Timespec.  Please note that ISO-8601 strings
+ *    are a representation of Universal Time (UTC), and as such, they
+ *    'store' UTC.  To make them human readable, they show timezone 
+ *    information along with a local-time string.  But fundamentally,
+ *    they *are* UTC.  Thus, thir routine takes a UTC input, and 
+ *    returns a UTC output.
+ *
+ *    For example: 1998-07-17 11:00:00.68-0500 
  *    is 680 milliseconds after 11 o'clock, central daylight time 
- *    \return The time in gmt. */
+ *    It is also 680 millisecs after 16:00:00 hours UTC.
+ *    \return The universl time.
+ *
+ * XXX Caution: this routine does not handle strings that specify
+ * times before January 1 1970.
+ */
 Timespec gnc_iso8601_to_timespec_gmt(const char *);
 
-/** The gnc_timespec_to_iso8601_buff() routine prints a Timespec
-* as an ISO-8601 style string.  The buffer must be long enough
-* to contain the NULL-terminated string (32 characters + NUL).  This
-* routine returns a pointer to the null terminator (and can 
-* thus be used in the 'stpcpy' metaphor of string concatenation).*/
+/** The gnc_timespec_to_iso8601_buff() routine takes the input 
+ *    UTC Timespec value and prints it as an ISO-8601 style string.  
+ *    The buffer must be long enough to contain the NULL-terminated 
+ *    string (32 characters + NUL).  This routine returns a pointer 
+ *    to the null terminator (and can thus be used in the 'stpcpy' 
+ *    metaphor of string concatenation).
+ *
+ *    Please note that ISO-8601 strings are a representation of 
+ *    Universal Time (UTC), and as such, they 'store' UTC.  To make them 
+ *    human readable, they show timezone information along with a 
+ *    local-time string.  But fundamentally, they *are* UTC.  Thus,
+ *    this routine takes a UTC input, and returns a UTC output.
+ *
+ *    The string generated by this routine uses the local timezone
+ *    on the machine on which it is executing to create the timestring.
+ */
 char * gnc_timespec_to_iso8601_buff (Timespec ts, char * buff);
 
 /** DOCUMENT ME! FIXME: Probably similar to xaccDMYToSec() this date
@@ -206,7 +236,12 @@
 
 /** \warning hack alert XXX FIXME -- these date routines return incorrect
  * values for dates before 1970.  Most of them are good only up 
- * till 2038.  This needs fixing ... */
+ * till 2038.  This needs fixing ... 
+ *
+ * XXX  This routine should be modified to assume that the 
+ * the user wanted the time at noon, localtime.  The returned 
+ * time_t should be seconds (at GMT) of the local noon-time.
+*/
 time_t xaccDMYToSec (int day, int month, int year);
 
 /** The gnc_timezone function returns the number of seconds *west*
Index: gnc-date.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-date.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -Lsrc/engine/gnc-date.c -Lsrc/engine/gnc-date.c -u -r1.8 -r1.9
--- src/engine/gnc-date.c
+++ src/engine/gnc-date.c
@@ -962,8 +962,8 @@
 /* hack alert -- this routine returns incorrect values for 
  * dates before 1970 */
 
-static Timespec
-gnc_iso8601_to_timespec(const char *str, int do_localtime)
+Timespec
+gnc_iso8601_to_timespec_gmt(const char *str)
 {
   char buf[4];
   Timespec ts;
@@ -987,7 +987,7 @@
   str = strchr (str, ':'); if (str) { str++; } else { return ts; }
   stm.tm_sec = atoi (str);
 
-  /* the decimal point, optionally present ... */
+  /* The decimal point, optionally present ... */
   /* hack alert -- this algo breaks if more than 9 decimal places present */
   if (strchr (str, '.')) 
   { 
@@ -999,7 +999,7 @@
   }
   stm.tm_isdst = -1;
 
-  /* timezone format can be +hh or +hhmm or +hh.mm (or -) (or not present) */
+  /* Timezone format can be +hh or +hhmm or +hh.mm (or -) (or not present) */
   str += strcspn (str, "+-");
   if (str)
   {
@@ -1024,8 +1024,12 @@
     }
   }
 
-  /* adjust for the local timezone */
-  if (do_localtime)
+  /* Note that mktime returns 'local seconds' which is the true time
+   * minus the timezone offset.  We don't want to work with local 
+   * seconds, since they swim around acording to daylight savings, etc. 
+   * We want to work with universal time.  Thus, add an offset
+   * to undo the damage that mktime causes.
+   */
   {
     struct tm tmp_tm;
     struct tm *tm;
@@ -1054,25 +1058,12 @@
     stm.tm_isdst = tmp_tm.tm_isdst;
   }
 
-  /* compute number of seconds */
   ts.tv_sec = mktime (&stm);
   ts.tv_nsec = nsec;
 
   return ts;
 }
 
-Timespec
-gnc_iso8601_to_timespec_local(const char *str)
-{
-   return gnc_iso8601_to_timespec(str, 1);
-}
-
-Timespec
-gnc_iso8601_to_timespec_gmt(const char *str)
-{
-   return gnc_iso8601_to_timespec(str, 0);
-}
-
 /********************************************************************\
 \********************************************************************/
 
@@ -1093,8 +1084,8 @@
   if (0>tz_min) { tz_min +=60; tz_hour --; }
   if (60<=tz_min) { tz_min -=60; tz_hour ++; }
 
-  /* we also have to print the sign by hand, to work around a bug
-   * in the glibc 2.1.3 printf (where %+02d fails to zero-pad)
+  /* We also have to print the sign by hand, to work around a bug
+   * in the glibc 2.1.3 printf (where %+02d fails to zero-pad).
    */
   cyn = '-';
   if (0>tz_hour) { cyn = '+'; tz_hour = -tz_hour; }
@@ -1111,7 +1102,7 @@
                  tz_hour,
                  tz_min);
 
-  /* return pointer to end of string */
+  /* Return pointer to end of string. */
   buff += len;
   return buff;
 }


More information about the Gnucash-changes mailing list