delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/12/20/16:06:32

From: Jason Green <news AT jgreen4 DOT fsnet DOT co DOT uk>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: strftime: Need Help with Time Offsets
Date: Wed, 20 Dec 2000 20:54:29 +0000
Organization: Customer of Energis Squared
Lines: 133
Message-ID: <1a524t0tk28cmv3vqfq26tooe0qeikhgm5@4ax.com>
References: <3a39c060 DOT 1329770 AT corp DOT supernews DOT net>
NNTP-Posting-Host: modem-62.medroxyprogest.dialup.pol.co.uk
Mime-Version: 1.0
X-Trace: news5.svr.pol.co.uk 977345687 7687 62.136.88.190 (20 Dec 2000 20:54:47 GMT)
NNTP-Posting-Date: 20 Dec 2000 20:54:47 GMT
X-Complaints-To: abuse AT theplanet DOT net
X-Newsreader: Forte Agent 1.7/32.534
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

ftilley AT azstarnet DOT cyberbromo DOT com (Felix Tilley) wrote:

> All of the GMT offsets are wrong.  Dates and times are correct, but
> the GMT offsets are wrong.

There appears to be a bug in strftime() when using the %z format.

Well, actually not so much a bug as a feature. ;-)

At the moment, the number of seconds offset from GMT is used, unless
it is negative, in which case 0000 is used.

I've patched strftime.c to fix this.  The patch is attached at the
bottom of this message.  There is also some more test code to
demonstrate the problem.

Note: The original code posted by Felix, poked values into the
tm_gmtoff and tm_zone fields to simulate a time-zone shift.  I don't
know if that's a valid method (mktime() seems to reset those fields
without using their values) but it works well enough as a test case
for this patch.

With existing strftime the test program outputs:

Wed, 20 Dec 2000 20:35:42 +0000 GMT
Wed, 20 Dec 2000 20:35:42 +0000 GMT
Wed, 20 Dec 2000 08:01:42 -0000 TEST1
Thu, 21 Dec 2000 09:09:42 +45240 TEST2

After patching the test program outputs:

Wed, 20 Dec 2000 20:36:21 +0000 GMT
Wed, 20 Dec 2000 20:36:21 +0000 GMT
Wed, 20 Dec 2000 08:02:21 -1234 TEST1
Thu, 21 Dec 2000 09:10:21 +1234 TEST2

Here is the test program:

/******************* start of test code ********************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

void PrintTime(const char *fmt, const struct tm *tm);

int main(void)
{
    time_t now;
    struct tm *tm;
    const char *fmt = "%a, %d %b %Y %X %z %Z";
    
    time(&now);         
    
    PrintTime(fmt, gmtime(&now));
        
    PrintTime(fmt, localtime(&now));
    
    tm = gmtime(&now);      
    
    tm->tm_hour -= 12;
    tm->tm_min  -= 34;
    
    tm->tm_gmtoff = difftime(mktime(tm), now);
    tm->tm_zone = "TEST1";

    PrintTime(fmt, tm);
    
    tm = gmtime(&now);      
    
    tm->tm_hour += 12;
    tm->tm_min  += 34;

    tm->tm_gmtoff = difftime(mktime(tm), now);
    tm->tm_zone = "TEST2";

    PrintTime(fmt, tm);
    
    return 0;
}

void PrintTime(const char *fmt, const struct tm *tm)
{
    char str[256];
    
    if (strftime(str, sizeof(str), fmt, tm) > 0)
        puts(str);
    else
        puts("oops!");
}
/******************* end of test code ********************/

Here is the patch:

--- src/libc/ansi/time/strftime.c.orig  Thu Jun  3 13:27:34 1999
+++ src/libc/ansi/time/strftime.c       Wed Dec 20 19:25:00 2000
@@ -61,6 +61,8 @@
 static size_t
 _fmt(const char *format, const struct tm *t, int upcase)
 {
+  long gmtoffset, gmtoffset_mins, gmtoffset_hrs;
+
   for (; *format; ++format)
   {
     if (*format == '%')
@@ -218,10 +220,23 @@
          return 0;
        continue;
       case 'z':
-       if (!_add(t->__tm_gmtoff<0 ? "-" : "+", 0))
-         return 0;
-       if (!_conv(t->__tm_gmtoff, 4, pad))
-         return 0;
+        gmtoffset_mins = (t->__tm_gmtoff / 60) % 60;
+        gmtoffset_hrs = t->__tm_gmtoff / 3600;
+        gmtoffset = (gmtoffset_hrs * 100) + gmtoffset_mins;
+       if (gmtoffset<0)
+       {
+         if (!_add("-", 0))
+           return 0;
+         if (!_conv(-gmtoffset, 4, pad))
+           return 0;
+       }
+       else
+       {
+         if (!_add("+", 0))
+           return 0;
+         if (!_conv(gmtoffset, 4, pad))
+           return 0;
+       }
        continue;
       case 'Z':
        if (!t->tm_zone || !_add(t->tm_zone, upcase))

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019