Time zone conversion C API on Linux, anyone?

后端 未结 6 1239
终归单人心
终归单人心 2020-12-29 03:40

I\'m looking for something that I presumed would be very simple - given local Unix time in a specific time zone (specified as a string, e.g., \"America/New_York\" - note tha

6条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-29 04:02

    Wanted to add a bit more detail here.

    If you try the following:

    #include 
    #include     /* defines 'extern long timezone' */
    
    int main(int argc, char **argv)
    {
        time_t t, lt, gt;
        struct tm tm;
    
        t = time(NULL);
        lt = mktime(localtime(&t));
        gt = mktime(gmtime(&t));
    
        printf( "(t = time(NULL)) == %x,\n"
            "mktime(localtime(&t)) == %x,\n"
            "mktime(gmtime(&t)) == %x\n"
            "difftime(...) == %f\n"
            "timezone == %d\n", t, lt, gt,
            difftime(gt, lt), timezone);
        return 0;
    }
    

    you'll notice that timezone conversions make sure that:

    • mktime(localtime(t)) == t, and
    • mktime(gmtime(t)) == t + timezone,
      therefore:
    • difftime(mktime(gmtime(t)), mktime(localtime(t))) == timezone
      (the latter is a global variable initialized by either tzset() or the invocation of any timezone conversion function).

    Example output of the above:

    $ TZ=GMT ./xx
    (t = time(NULL)) == 4dd13bac,
    mktime(localtime(&t)) == 4dd13bac,
    mktime(gmtime(&t)) == 4dd13bac
    difftime(...) == 0.000000
    timezone == 0
    
    $ TZ=EST ./xx
    (t = time(NULL)) == 4dd13baf,
    mktime(localtime(&t)) == 4dd13baf,
    mktime(gmtime(&t)) == 4dd181ff
    difftime(...) == 18000.000000
    timezone == 18000
    
    $ TZ=CET ./xx
    (t = time(NULL)) == 4dd13bb2,
    mktime(localtime(&t)) == 4dd13bb2,
    mktime(gmtime(&t)) == 4dd12da2
    difftime(...) == -3600.000000
    timezone == -3600
    

    In that sense, you're attempting to "do it backwards" - time_t is treated as absolute in UN*X, i.e. always relative to the "EPOCH" (0:00 UTC on 01/01/1970).

    The difference between UTC and the current timezone (last tzset() call) is always in the external long timezone global.

    That doesn't get rid of the environment manipulation uglyness, but you can save yourself the effort of going through mktime().

提交回复
热议问题