Преобразование даты и времени UTC в UNIX Time дает неправильное (другой часовой пояс) значение.Зачем? - PullRequest
0 голосов
/ 22 января 2019

Я написал небольшую функцию для преобразования даты и времени в формате UTC во время UNIX (время эпохи).Однако значение, которое я получаю, зависит от часового пояса, в котором я нахожусь.

Вот код

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

time_t GenerateUnixTimeStampFromDateAndTime(char *DateAndTime);

void main()
{
    long int UnixTime=0;
    char *CurrentTime="01/22/2019 06:30:00";

    UnixTime = (long int)GenerateUnixTimeStampFromDateAndTime(CurrentTime);
    printf("Current Unix Time= %ld\r\n", UnixTime);
}

time_t GenerateUnixTimeStampFromDateAndTime(char *DateAndTime) 
{
    struct tm ti={0};
    if( sscanf(DateAndTime, "%d/%d/%d %d:%d:%d", &ti.tm_mon, &ti.tm_mday, &ti.tm_year, &ti.tm_hour, &ti.tm_min, &ti.tm_sec) != 6 )
        return -1;
    ti.tm_year = ti.tm_year - 1900;
    ti.tm_mon = ti.tm_mon - 1;

    return mktime(&ti);
}

Я получаю ответ 1548118800, который равен 01/22 /.2019 01:00:00, т.е. -5:30, это часовой пояс, в котором я нахожусь (Индия).Если я изменю часовой пояс своего компьютера на UTC, то это даст правильное значение 1548138600.

Какие изменения мне нужны, чтобы сделать его независимым от часового пояса?

1 Ответ

0 голосов
/ 22 января 2019

Как задокументировано, mktime() принимает компоненты разбитого времени в местное время .

Сначала сохраните текущий часовой пояс пользователя:

char  *old_timezone, *temp;

temp = getenv("TZ");
if (temp) {
    const size_t  len = temp;
    old_timezone = malloc(len + 1);
    if (!old_timezone) {
        fprintf(stderr, "Out of memory!\n");
        exit(EXIT_FAILURE);
    }
    if (len > 0)
        memcpy(old_timezone, temp, len);
    old_timezone[len] = '\0';
} else
    old_timezone = NULL;

Если пользователь использует системное значение по умолчанию, old_timezone будет НЕДЕЙСТВИТЕЛЕН.

Далее установите текущий часовой пояс (для этого процесса) в UTC:

setenv("TZ", "UTC", 1);
tzset();

Обратите внимание, что при желании вы можете использовать любой спецификатор часового пояса вместо "UTC" выше; см. tzset() для деталей. Вызов tzset() обычно выполняется изнутри вашей C-библиотекой, но выполнение этого в явном виде помогает нам понять, что только что произошло что-то специфическое для часового пояса.

В этот момент mktime() будет работать в UTC, а localtime() и gmtime() будут возвращать те же результаты.

Затем восстановите часовой пояс на

if (old_timezone) {
    setenv("TZ", old_timezone, 1);
    free(old_timezone);
    old_timezone = NULL;
} else
    unsetenv("TZ");
tzset();

Обратите внимание, что это не влияет ни на что, кроме текущего процесса (и любых дочерних процессов, которые вы можете создать с помощью popen() или system() или fork() и exec()). Часовой пояс, как и локаль, является свойством процесса.


Запуск

    unsetenv("TZ");
    tzset();

изменит текущий часовой пояс для этого процесса на системный часовой пояс по умолчанию.


Если ваша программа работает явно в формате UTC, вы можете сделать просто

    /* This program works explicitly in the UTC timezone.
       User/system timezone configuration is completely ignored. */
    setenv("TZ", "UTC", 1");
    tzset();

в начале вашего main().

...