Problems with time (now) Linux and Windows

Started by ale870, August 06, 2009, 08:32:05 AM

Previous topic - Next topic

TedWalther

#15
I found the problem.  gmtime() and localtime() (and a couple other functions) all put their result into the same underlying structure, and they return a pointer to it.  So when you are calling gmtime(), Lutz, you are blasting over the values put there by localtime().  I'll have a patch ready for you shortly.



By the way, that behavior is documented in the BSD manpage and is allowed by POSIX.



Ted
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

TedWalther

#16
Lutz, why are you using gettimeofday() instead of time()?



The fixed files newlisp.c and nl-filesys.c have been mailed to you.  Using the (corrected) BSD method for everything except WIN_32 saves 9 lines of code, although 5 of those lines were comments.  It shouldn't change the behavior for any platform.



On BSD, it is necessary to call tzset() before calling localtime(), and can't do any harm on other POSIX platforms.



Ted
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

TedWalther

#17
I did another test.  The call to tzset() may not even be necessary.  I'll see make an even smaller patch; if that works on all platforms, then the bigger patch can be tossed.  I just wanted to be extra safe.



[some time later...]



Although it seems to work without tzset(), tzset() should be called for another reason; using tzset() makes calls to localtime() utilize the environment variable TZ, allowing users to set the timezone on the fly in the traditional Unix method.



The new, less intrusive patch reduces the lines of code by 12, and I suspect I could cut out another couple lines of code; do AIX, TRU64, and OS2 all not support tzset(), gettimeofday(), localtime(), and gmtime()?



Ted
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

TedWalther

#18

--- n1/newlisp.c        Sat Aug  8 12:15:17 2009
+++ n3/newlisp.c        Sat Aug  8 21:33:39 2009
@@ -593,6 +593,7 @@
 #ifndef OS2
 pagesize = getpagesize();
 #endif
+tzset();
 #endif
 
 initLocale();
diff -ru n1/nl-filesys.c n3/nl-filesys.c
--- n1/nl-filesys.c     Sat Aug  8 12:15:17 2009
+++ n3/nl-filesys.c     Sat Aug  8 21:28:03 2009
@@ -2315,29 +2315,26 @@
 {
 struct timeval tv;
 struct tm *ttm;
-#ifdef _BSD
-struct tm *ltm;
-#endif
 #ifdef WIN_32
 TIME_ZONE_INFORMATION timeZone;
+#else
+UINT _gmt_offset;
+UINT _dst_predicate;
 #endif
-/* struct timezone tzp; obsolete? */
-ssize_t offset = 0;
 
 gettimeofday(&tv, NULL);
 
 if(params != nilCell)
        {
        getInteger(params, NULL);
-       offset *= 60;
-        tv.tv_sec += offset;
        }
 
-#ifdef _BSD
-ltm = localtime((time_t *)&tv.tv_sec);
-#endif
 #ifdef WIN_32
 GetTimeZoneInformation(&timeZone);
+#else
+ttm = localtime((time_t *)&tv.tv_sec);
+_gmt_offset = (UINT)ttm->tm_gmtoff;
+_dst_predicate = (UINT)ttm->tm_isdst;
 #endif
 
 ttm = gmtime((time_t *)&tv.tv_sec);
@@ -2353,28 +2350,18 @@
     (UINT)tv.tv_usec,
     (UINT)ttm->tm_yday + 1,
     (UINT)ttm->tm_wday + 1,
-
-#if defined(MAC_OSX) || defined(LINUX) || defined(SUNOS)
-    (UINT)timezone / 60, (UINT)daylight
-#endif
-#if defined(_BSD)
-/* this is as of BSD docs but will work only Mac OS X.
-   FreeBSD and OpenBSD give 0, 0
-    (long)tzp.tz_minuteswest, (long)tzp.tz_dsttime
-   and the following doesn't work either, -> 0, 0
-*/
-    (UINT)ltm->tm_gmtoff, (UINT)ltm->tm_isdst
-#endif
 #if defined(WIN_32)
      timeZone.Bias,
      timeZone.DaylightBias    
-#endif
-#if defined(OS2) || defined(TRU64) || defined(AIX)
+#elif defined(OS2) || defined(TRU64) || defined(AIX)
 #ifdef NEWLISP64
     (UINT)0L, (UINT)0L
 #else
     (UINT)0, (UINT)0
 #endif
+#else
+     _gmt_offset,
+     _dst_predicate
 #endif
     ));
 }
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

TedWalther

#19
I got the code wrong; I hadn't looked closely at what value the offset was supposed to hold; tm_gmtoff holds seconds east of GMT, rather than the minutes west of GMT we are trying to return.  Here is the fix:



diff -ru n3/nl-filesys.c n4/nl-filesys.c
--- n3/nl-filesys.c     Sat Aug  8 21:41:03 2009
+++ n4/nl-filesys.c     Sat Aug  8 22:24:39 2009
@@ -2333,7 +2333,7 @@
 GetTimeZoneInformation(&timeZone);
 #else
 ttm = localtime((time_t *)&tv.tv_sec);
-_gmt_offset = (UINT)ttm->tm_gmtoff;
+_gmt_offset = (UINT) (((ttm->tm_gmtoff > 0) ? 86400 - ttm->tm_gmtoff : 0 - ttm->tm_gmtoff) / 60);
 _dst_predicate = (UINT)ttm->tm_isdst;
 #endif
 
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.