C code to get local time offset in minutes relative to UTC?

后端 未结 5 2279
不思量自难忘°
不思量自难忘° 2021-02-20 07:40

I didn\'t find a trivial way to get the time offset in minutes between the local time and the UTC time.

At first I intended to use tzset() but it doesn\'t p

5条回答
  •  无人及你
    2021-02-20 08:01

    ... to get local time offset ... relative to UTC?

    @Serge Ballesta answer is good. So I though I would test it and clean-up a few details. I would have posted as a comment but obviously too big for that. I only exercised it for my timezone, but though others may want to try on their machine and zone.

    I made to community wiki as not to garner rep. Imitation is the sincerest form of flattery

    This answer is akin to @trenki except that it subtracts nearby struct tm values instead of assuming DST shift is 1 hour and time_t is in seconds.

    #include 
    #include 
    #include 
    #include 
    
    // return difference in **seconds** of the tm_mday, tm_hour, tm_min, tm_sec members.
    long tz_offset_second(time_t t) {
      struct tm local = *localtime(&t);
      struct tm utc = *gmtime(&t);
      long diff = ((local.tm_hour - utc.tm_hour) * 60 + (local.tm_min - utc.tm_min))
              * 60L + (local.tm_sec - utc.tm_sec);
      int delta_day = local.tm_mday - utc.tm_mday;
      // If |delta_day| > 1, then end-of-month wrap 
      if ((delta_day == 1) || (delta_day < -1)) {
        diff += 24L * 60 * 60;
      } else if ((delta_day == -1) || (delta_day > 1)) {
        diff -= 24L * 60 * 60;
      }
      return diff;
    }
    
    void testtz(void) {
      long off = -1;
      int delta = 600;
      for (time_t t = 0; t < LONG_MAX-delta; t+=delta) {
        long off2 = tz_offset_second(t);
    
        // Print time whenever offset changes.
        if (off != off2) {
          struct tm utc = *gmtime(&t);
          printf("%10jd %04d-%02d-%02dT%02d:%02d:%02dZ\n", (intmax_t) t,
                  utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday,
                  utc.tm_hour, utc.tm_min, utc.tm_sec);
          struct tm local = *localtime(&t);
          off = off2;
          printf("%10s %04d-%02d-%02d %02d:%02d:%02d %2d %6ld\n\n", "",
                  local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,
                  local.tm_hour, local.tm_min, local.tm_sec, local.tm_isdst ,off);
          fflush(stdout);
        }
      }
      puts("Done");
    }
    

    Output

                                      v----v  Difference in seconds
             0 1970-01-01T00:00:00Z
               1969-12-31 18:00:00  0 -21600
    
       5731200 1970-03-08T08:00:00Z
               1970-03-08 03:00:00  1 -18000
    
      26290800 1970-11-01T07:00:00Z
               1970-11-01 01:00:00  0 -21600
    
    ...
    
    2109222000 2036-11-02T07:00:00Z
               2036-11-02 01:00:00  0 -21600
    
    2120112000 2037-03-08T08:00:00Z
               2037-03-08 03:00:00  1 -18000
    
    2140671600 2037-11-01T07:00:00Z
               2037-11-01 01:00:00  0 -21600
    
    Done
    

提交回复
热议问题