ashkang / jcal

Jalali Calendar Library
http://nongnu.org/jcal
139 stars 24 forks source link

`jmktime` and `jstrftime` depend on GMT offset #4

Closed reith closed 9 years ago

reith commented 10 years ago

It's not standard for jmktime or jstrftime to depend on jtm.tm_gmtoff. Instead they should use local timezone values. At-least for strftime it said in POSIX.1-2008:

Local timezone information is used as though strftime() called tzset().

Current approach makes timezone unaware transforms hard.

This is a test showing incompatibilities with Linux glibc:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <jtime.h>
#include <jalali.h>

char b[100];
#define print_ts_z(frm, tm, f) {f(b, 100, frm, &tm); puts(b);}

void print_tm(const struct tm* tm) {
    printf("year: %d\nmonth: %d\nday: %d\nhour: %d\nminute: %d\nsecond: %d\n" \
                 "yday: %d\nwday: %d\nisdst: %d\ngmtoff: %ld\nzone: %s\n", tm->tm_year,
                 tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, 
                 tm->tm_yday, tm->tm_wday, tm->tm_isdst, tm->tm_gmtoff, tm->tm_zone); 
}

int jmktime_test() {
    struct tm tm;
    time_t ts;

    time(&ts);
    localtime_r(&ts, &tm);
    tm.tm_gmtoff = 0;
    tm.tm_zone = NULL;
    printf("mktime on zeroed tz-> %ld\n", mktime(&tm));
    print_tm(&tm);

    puts("******");

    struct jtm jtm;
    jlocaltime_r(&ts, &jtm);
    jtm.tm_gmtoff = 0;
    jtm.tm_zone = NULL;
    printf("jmktime on zeroed tz-> %ld\n", jmktime(&jtm));
    print_tm((const struct tm*)&jtm);

    return 0;
}

int jstrftime_test() {
    struct tm tm;
    time_t ts;

    time(&ts);
    localtime_r(&ts, &tm);
    print_ts_z("strftime '%%s' on localtime output: %s", tm, strftime);
    tm.tm_gmtoff = 0;
    tm.tm_zone = NULL;
    print_ts_z("strftime '%%s' on zeroed zone: %s", tm, strftime);

    struct jtm jtm;
    jlocaltime_r(&ts, &jtm);
    print_ts_z("jstrftime '%%s' on localtime output: %s", jtm, jstrftime);
    jtm.tm_gmtoff = 0;
    tm.tm_zone = NULL;
    print_ts_z("jstrftime '%%s' on zeroed zone: %s", jtm, jstrftime);
    return 0;
}

int main() {
    puts("****  jstrftime() test  ****");
    jstrftime_test();
    puts("\n****  jmktime() test  ****");
    jmktime_test();
    return 0;
}

The output I've got on a machine with non-UTC localtime:

****  jstrftime() test  ****
strftime '%s' on localtime output: 1385304535
strftime '%s' on zeroed zone: 1385304535
jstrftime '%s' on localtime output: 1385304535
jstrftime '%s' on zeroed zone: 1385317135

****  jmktime() test  ****
mktime on zeroed tz-> 1385304535
year: 113
month: 10
day: 24
hour: 18
minute: 18
second: 55
yday: 327
wday: 0
isdst: 0
gmtoff: 12600
zone: IRST
******
jmktime on zeroed tz-> 1385317135
year: 1392
month: 8
day: 3
hour: 18
minute: 18
second: 55
yday: 248
wday: 1
isdst: 0
gmtoff: 0
zone: (null)
reith commented 9 years ago

look fixed as of ca668b4324f298d1ef69a49880c1118167caffa9 by doing jalali-update in jmktime