diff src/util.c @ 259:b660fadc1814 noffle

[svn] * src/server.c,src/util.c,src/util.h: Recognise GMT/UTC on NNTP NEWGROUPS. Do small reorg of some of the timezone sensitive code, and introduce use of timegm(). An implementation is provided for systems without timegm().
author bears
date Wed, 26 Jun 2002 14:30:26 +0100
parents 4e69e9b722ae
children 3477050e8d10
line wrap: on
line diff
--- a/src/util.c	Wed Jun 26 14:29:02 2002 +0100
+++ b/src/util.c	Wed Jun 26 14:30:26 2002 +0100
@@ -1,7 +1,7 @@
 /*
   util.c
 
-  $Id: util.c 375 2002-03-15 10:50:33Z bears $
+  $Id: util.c 391 2002-06-26 13:30:26Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -294,14 +294,15 @@
 			     "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
 
 /*
- * Calculate the difference between local time and GMT. This is INN's
- * 'always-works' method. It assumes the time differences is < 24hrs.
- * Sounds reasonable to me. It also assumes it can ignore seconds.
- * Returns GMT - localtime minutes. It will also trash the localtime/
+ * Calculate the difference between local time and GMT at GMT time t.
+ *
+ * This is INN's 'always-works' method. It assumes the time differences
+ * is < 24hrs. Sounds reasonable to me. It also assumes it can ignore seconds.
+ * Returns localtime - GMT seconds. It will also trash the localtime/
  * gmtime/etc. static buffer.
  */
 static int
-tzDiff( void )
+localTimeDiff( time_t t )
 {
     time_t now;
     struct tm local, gmt, *tm;
@@ -312,25 +313,26 @@
     if ( now < nextCalc )
 	return res;
     
-    tm = localtime( &now );
+    tm = localtime( &t );
     if ( tm == NULL )
 	return 0;
     local = *tm;
-    tm = gmtime( &now );
+    tm = gmtime( &t );
     if ( tm == NULL )
 	return 0;
     gmt = *tm;
 
-    res = gmt.tm_yday - local.tm_yday;
+    res = local.tm_yday - gmt.tm_yday;
     if ( res < -1 )
 	res = -1;		/* Year rollover? */
     else if ( res > 1 )
 	res = 1;
 
     res *= 24;
-    res += gmt.tm_hour - local.tm_hour;
+    res += local.tm_hour - gmt.tm_hour;
     res *= 60;
-    res += gmt.tm_min - local.tm_min;
+    res += local.tm_min - gmt.tm_min;
+    res *= 60;
 
     /* Need to recalc at start of next hour */
     nextCalc = now + ( 60 - local.tm_sec ) + 60 * ( 59 - local.tm_min );
@@ -338,13 +340,39 @@
     return res;
 }
 
+time_t
+Utl_mktimeGMT( struct tm *t )
+{
+#if HAVE_TIMEGM
+    return timegm( t );
+#else    
+    /*
+     * Based on the portable implementation suggested in the glibc man page
+     * for timegm.
+     */
+    time_t ret;
+    char *tz;
+
+    tz = getenv("TZ");
+    setenv("TZ", "", 1);
+    tzset();
+    ret = mktime(t);
+    if (tz)
+	setenv("TZ", tz, 1);
+    else
+	unsetenv("TZ");
+    tzset();
+    return ret;
+#endif    
+}
+
 void
 Utl_newsDate( time_t t, Str res )
 {    
     struct tm *local;
     long tzdiff, hoffset, moffset;
 
-    tzdiff = - tzDiff();
+    tzdiff = localTimeDiff( t ) / 60;
 
     local = localtime( &t );
     if ( local == NULL )
@@ -463,16 +491,13 @@
     if ( *s != '\0' && ! isspace( *s ) )
 	return (time_t) -1;
 
-    res = mktime( &tm );
+    res = Utl_mktimeGMT( &tm );
     if ( res == (time_t) -1 )
 	return res;
     
     if ( wday >= 0 && wday != tm.tm_wday )
 	return (time_t) -1;
 
-    /* Remove local time diff from res to give time as if GMT */
-    res -= tzDiff() * 60;
-
     /* And now adjust for tzoffset */
     res -= tzoffset * 60;