简体   繁体   中英

Why are gmtime_r and localtime_r returning same time?

The code is:

#include <stdio.h>
#include <time.h>

int main(void)

{

    time_t t, nt;  /* seconds time holder */
    struct tm gmt; /* time structure gmt */
    struct tm lcl; /* local time structure */

    t = time(NULL); /* get seconds time */
    gmtime_r(&t, &gmt); /* get gmt */
    localtime_r(&t, &lcl); /* get local */

    printf("gmt hour: %d local hour: %d\n", gmt.tm_hour, lcl.tm_hour);

}

The run is:

samiam@samiam-h-pc-2:~/projects/petit_ami$ gcc -o test test.c
samiam@samiam-h-pc-2:~/projects/petit_ami$ ./test
gmt hour: 20 local hour: 20
samiam@samiam-h-pc-2:~/projects/petit_ami$ date
Sat 17 Jul 2021 08:28:43 PM PST
samiam@samiam-h-pc-2:~/projects/petit_ami$ 

The answers I have found so far talk about the use of localtime() (not localtime_r), or not having the timezone set, but you can see from above that was done.

This is on Ubuntu 20.04.

Thanks,

Scott Franco San Jose, CA

Ok, playing with the date command:

samiam@samiam-h-pc-2:~/projects/petit_ami$ date
Sat 17 Jul 2021 08:28:43 PM PST

Is wrong, the time is 1:38pm (13:38), and the clock on the desktop shows the same. Trying to fix that:

samiam@samiam-h-pc-2:~/projects/petit_ami$ hwclock -r
hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --verbose option to see the details of our search for an access method.
Sat 17 Jul 2021 01:38:00 PM PST
samiam@samiam-h-pc-2:~/projects/petit_ami$ sudo date -s "july 17 2021 13:38"
Sat 17 Jul 2021 01:38:00 PM PST
samiam@samiam-h-pc-2:~/projects/petit_ami$ date
Sat 17 Jul 2021 08:38:42 PM PST
samiam@samiam-h-pc-2:~/projects/petit_ami$ 

oooooooo ok. Humm...

Clearly I am fighting with the time server, but not sure what is going on.

samiam@samiam-h-pc-2:~/projects/petit_ami$ timedatectl
               Local time: Sat 2021-07-17 13:46:51 PDT     
           Universal time: Sat 2021-07-17 20:46:51 UTC     
                 RTC time: Sat 2021-07-17 20:46:52         
                Time zone: America/Los_Angeles (PDT, -0700)
System clock synchronized: no                              
              NTP service: n/a                             
          RTC in local TZ: no                              
samiam@samiam-h-pc-2:~/projects/petit_ami$ ./test
gmt hour: 20 local hour: 20
samiam@samiam-h-pc-2:~/projects/petit_ami$ 

Requested by Steve:

samiam@samiam-h-pc-2:~/Desktop$ ls -l /etc/localtime
lrwxrwxrwx 1 root root 39 Feb 23 21:41 /etc/localtime -> /usr/share/zoneinfo/America/Los_Angeles
samiam@samiam-h-pc-2:~/Desktop$ wc /etc/localtime
   8   86 2836 /etc/localtime
samiam@samiam-h-pc-2:~/projects/petit_ami$ echo $TZ
PST8PDT
samiam@samiam-h-pc-2:~/projects/petit_ami$ ./test
gmt hour: 21 local hour: 14
samiam@samiam-h-pc-2:~/projects/petit_ami$ 
samiam@samiam-h-pc-2:~/Desktop$ pa
samiam@samiam-h-pc-2:~/projects/petit_ami$ echo $TZ
America/Los_Angeles
samiam@samiam-h-pc-2:~/projects/petit_ami$ ./test
gmt hour: 21 local hour: 14
samiam@samiam-h-pc-2:~/projects/petit_ami$

This addresses the answer given by Steve:

samiam@samiam-h-pc-2:~/projects/petit_ami$ ls -l /etc/localtime
lrwxrwxrwx 1 root root 39 Feb 23 13:41 /etc/localtime -> /usr/share/zoneinfo/America/Los_Angeles
samiam@samiam-h-pc-2:~/projects/petit_ami$ echo $TZ
America/Los_Angeles
samiam@samiam-h-pc-2:~/projects/petit_ami$ ./test
gmt hour: 21 local hour: 14
samiam@samiam-h-pc-2:~/projects/petit_ami$ export TZ=""
samiam@samiam-h-pc-2:~/projects/petit_ami$ echo $TZ

samiam@samiam-h-pc-2:~/projects/petit_ami$ ./test
gmt hour: 21 local hour: 21
samiam@samiam-h-pc-2:~/projects/petit_ami$ 

Requested by KamilCuk:

samiam@samiam-h-pc-2:~/projects/petit_ami$ zdump -v -c 2019,2022 /etc/localtime
/etc/localtime  -9223372036854775808 = NULL
/etc/localtime  -9223372036854689408 = NULL
/etc/localtime  Sun Mar 10 09:59:59 2019 UT = Sun Mar 10 01:59:59 2019 PST isdst=0 gmtoff=-28800
/etc/localtime  Sun Mar 10 10:00:00 2019 UT = Sun Mar 10 03:00:00 2019 PDT isdst=1 gmtoff=-25200
/etc/localtime  Sun Nov  3 08:59:59 2019 UT = Sun Nov  3 01:59:59 2019 PDT isdst=1 gmtoff=-25200
/etc/localtime  Sun Nov  3 09:00:00 2019 UT = Sun Nov  3 01:00:00 2019 PST isdst=0 gmtoff=-28800
/etc/localtime  Sun Mar  8 09:59:59 2020 UT = Sun Mar  8 01:59:59 2020 PST isdst=0 gmtoff=-28800
/etc/localtime  Sun Mar  8 10:00:00 2020 UT = Sun Mar  8 03:00:00 2020 PDT isdst=1 gmtoff=-25200
/etc/localtime  Sun Nov  1 08:59:59 2020 UT = Sun Nov  1 01:59:59 2020 PDT isdst=1 gmtoff=-25200
/etc/localtime  Sun Nov  1 09:00:00 2020 UT = Sun Nov  1 01:00:00 2020 PST isdst=0 gmtoff=-28800
/etc/localtime  Sun Mar 14 09:59:59 2021 UT = Sun Mar 14 01:59:59 2021 PST isdst=0 gmtoff=-28800
/etc/localtime  Sun Mar 14 10:00:00 2021 UT = Sun Mar 14 03:00:00 2021 PDT isdst=1 gmtoff=-25200
/etc/localtime  Sun Nov  7 08:59:59 2021 UT = Sun Nov  7 01:59:59 2021 PDT isdst=1 gmtoff=-25200
/etc/localtime  Sun Nov  7 09:00:00 2021 UT = Sun Nov  7 01:00:00 2021 PST isdst=0 gmtoff=-28800
/etc/localtime  9223372036854689407 = NULL
/etc/localtime  9223372036854775807 = NULL
samiam@samiam-h-pc-2:~/projects/petit_ami$ ls -l /etc/localtime
lrwxrwxrwx 1 root root 39 Feb 23 21:41 /etc/localtime -> /usr/share/zoneinfo/America/Los_Angeles
samiam@samiam-h-pc-2:~/projects/petit_ami$ ls -l /usr/share/zoneinfo/America/Los_Angeles
-rw-r--r-- 1 root root 2836 Jan 27 21:32 /usr/share/zoneinfo/America/Los_Angeles
samiam@samiam-h-pc-2:~/projects/petit_ami$

On a Linux system, there are normally two ways to set the time zone:

  1. The file /etc/localtime is normally a symbolic link to one of the zoneinfo files from the tz database. For example, on my local machine (a Mac), it points to /var/db/timezone/zoneinfo/America/New_York , and on a Debian server I have access to in Seattle, it points to /usr/share/zoneinfo/America/Los_Angeles . In any case, /etc/localtime sets the machine's default time zone.

  2. The environment variable $TZ can be used on a per-process basis to override the system default. $TZ can be used in two different ways: (a) it can contain the name of a file in the tz database, or (b) it can contain a string like PST8PDT that specifies the time zone directly.

When you call one of the localtime functions, it normally consults $TZ or /etc/localtime to find the information it needs to convert a UTC time to local time.

You have discovered that explicitly setting your $TZ variable fixes your problem. This suggests there may be something wrong with your system's copy of the tz database.

On your system, in its default mode, and although /etc/localtime seems to be pointing to the zonefile for America/Los_Angeles , both your test program and the system date command are acting like they're on UTC. Also the system date command is wrongly (doubly wrongly) reporting PST, neither the PDT you're on nor the UTC that it's actually reporting the hour of.

And yet when you set TZ to America/Los_Angeles , it also worked, suggesting that your tz file is fine.

All I can say at this point is that modern Linux distros (Ubuntu in particular) have been radically rewriting things that had been stable for years and that I thought I understood. I think I heard that ntpd had fallen victim to the borglike embrace of systemd , so perhaps the tz database has, too, and this is affecting your results in some bizarre way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM