将 UTC 日期和时间转换为 UNIX 时间会给出错误的(时区不同的)值。为什么?
Conversion of UTC Date and Time to UNIX Time gives wrong (time zone different) value. Why?
我写了一个小函数来将 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,这是我所在的时区(印度)。如果我将我的 PC 时区更改为 UTC,那么它会给出正确的值 1548138600。
我需要做哪些更改才能使其与时区无关?
如文档所述,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] = '[=10=]';
} else
old_timezone = NULL;
如果用户使用系统默认值,old_timezone
将为NULL。
接下来,将当前时区(对于此过程)设置为 UTC:
setenv("TZ", "UTC", 1);
tzset();
请注意,如果需要,您可以使用任何时区说明符代替上面的 "UTC"
;有关详细信息,请参阅 tzset()
。 tzset()
调用通常由您的 C 库在内部完成,但在这里明确地进行调用可以帮助我们人类看到刚刚发生了特定于时区的事情。
此时,mktime()
将以 UTC 运行,localtime()
和 gmtime()
将 return 得到相同的结果。
之后,通过
恢复时区
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()
.
开头附近
我写了一个小函数来将 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,这是我所在的时区(印度)。如果我将我的 PC 时区更改为 UTC,那么它会给出正确的值 1548138600。
我需要做哪些更改才能使其与时区无关?
如文档所述,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] = '[=10=]';
} else
old_timezone = NULL;
如果用户使用系统默认值,old_timezone
将为NULL。
接下来,将当前时区(对于此过程)设置为 UTC:
setenv("TZ", "UTC", 1);
tzset();
请注意,如果需要,您可以使用任何时区说明符代替上面的 "UTC"
;有关详细信息,请参阅 tzset()
。 tzset()
调用通常由您的 C 库在内部完成,但在这里明确地进行调用可以帮助我们人类看到刚刚发生了特定于时区的事情。
此时,mktime()
将以 UTC 运行,localtime()
和 gmtime()
将 return 得到相同的结果。
之后,通过
恢复时区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()
.