- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图了解 UNIX timelocal 和 mktime 的工作原理。据说,当您在 struct tm tm_isdst 字段中传递正确的值时,它们会处理夏令时。
我正在测试一个非常特定的时刻。根据“America/New_York”的时区数据库,夏令时于 2005 年 10 月 30 日 01:00 发生变化。以下是 zdump -v America/New_York
的输出,您可以在自己的系统上确认。我仅显示 2005 年左右的数据子集(向右滚动以查看 gmtoff 值):
America/New_York Sun Apr 3 06:59:59 2005 UT = Sun Apr 3 01:59:59 2005 EST isdst=0 gmtoff=-18000America/New_York Sun Apr 3 07:00:00 2005 UT = Sun Apr 3 03:00:00 2005 EDT isdst=1 gmtoff=-14400America/New_York Sun Oct 30 05:59:59 2005 UT = Sun Oct 30 01:59:59 2005 EDT isdst=1 gmtoff=-14400America/New_York Sun Oct 30 06:00:00 2005 UT = Sun Oct 30 01:00:00 2005 EST isdst=0 gmtoff=-18000America/New_York Sun Apr 2 06:59:59 2006 UT = Sun Apr 2 01:59:59 2006 EST isdst=0 gmtoff=-18000America/New_York Sun Apr 2 07:00:00 2006 UT = Sun Apr 2 03:00:00 2006 EDT isdst=1 gmtoff=-14400
To test this transition I am setting up a struct tm
to contain 01:30 on that specific day. If I pass 0 for tm_isdst
it should give me a gmtoffset of -18000. If I pass 1 and enable daylight savings, then gmtoffset should be -14400.
Here's the code I'm using to test on both Darwin/OSX and FreeBSD:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void print_tm(struct tm* tm) {
printf("tm: sec [%d] min [%d] hour [%d] mday [%d] mon [%d] year [%d] wday [%d] yday [%d] isdst [%d] zone [%s] gmtoff [%ld]\n",
tm->tm_sec,
tm->tm_min,
tm->tm_hour,
tm->tm_mday,
tm->tm_mon + 1,
tm->tm_year,
tm->tm_wday,
tm->tm_yday + 1,
tm->tm_isdst,
tm->tm_zone,
tm->tm_gmtoff);
}
struct tm* set_tm(int sec, int min, int hour, int mday, int mon, int year, int wday, int yday, int isdst, int gmtoff, char* zone) {
struct tm* tm;
tm = malloc(sizeof(struct tm));
memset(tm, 0, sizeof(struct tm));
tm->tm_sec = sec;
tm->tm_min = min;
tm->tm_hour = hour;
tm->tm_mday = mday;
tm->tm_mon = mon - 1;
tm->tm_year = year;
tm->tm_wday = wday;
tm->tm_yday = yday - 1;
tm->tm_isdst = isdst;
tm->tm_zone = zone;
tm->tm_gmtoff = gmtoff;
return tm;
}
void test_timelocal(struct tm* tm, int isdst) {
time_t seconds = -1;
if(!setenv("TZ", "America/New_York", 1)) {
printf("isdst is [%d]\n", isdst);
tm->tm_isdst = isdst;
tzset();
seconds = timelocal(tm);
localtime_r(&seconds, tm);
print_tm(tm);
} else {
printf("setenv failed with [%s]\n", strerror(errno));
}
printf("\n");
}
void test_mktime(struct tm* tm, int isdst) {
time_t seconds = -1;
if(!setenv("TZ", "America/New_York", 1)) {
printf("isdst is [%d]\n", isdst);
tm->tm_isdst = isdst;
tzset();
seconds = mktime(tm);
localtime_r(&seconds, tm);
print_tm(tm);
} else {
printf("setenv failed with [%s]\n", strerror(errno));
}
printf("\n");
}
int main(void) {
struct tm* tm;
printf("Test with timelocal\n");
tm = set_tm(0, 30, 1, 30, 10, 2005, 0, 0, 0, 0, "");
test_timelocal(tm, 0);
tm = set_tm(0, 30, 1, 30, 10, 2005, 0, 0, 0, 0, "");
test_timelocal(tm, 1);
tm = set_tm(0, 30, 1, 30, 10, 2005, 0, 0, 0, 0, "");
test_timelocal(tm, -1);
printf("Test with mktime\n");
tm = set_tm(0, 30, 1, 30, 10, 2005, 0, 0, 0, 0, "");
test_mktime(tm, 0);
tm = set_tm(0, 30, 1, 30, 10, 2005, 0, 0, 0, 0, "");
test_mktime(tm, 1);
tm = set_tm(0, 30, 1, 30, 10, 2005, 0, 0, 0, 0, "");
test_mktime(tm, -1);
return 0;
}
在不同的操作系统上运行它会产生不同的结果。在 FreeBSD 上,此代码输出(向右滚动以查看 gmtoffset 值):
Test with timelocalisdst is [0]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [1] zone [EDT] gmtoff [-14400]isdst is [1]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [1] zone [EDT] gmtoff [-14400]isdst is [-1]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [1] zone [EDT] gmtoff [-14400]Test with mktimeisdst is [0]tm: sec [0] min [30] hour [2] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [1] zone [EDT] gmtoff [-14400]isdst is [1]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [1] zone [EDT] gmtoff [-14400]isdst is [-1]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [1] zone [EDT] gmtoff [-14400]
在 darwin/OSX 上,完全相同的代码会产生以下结果(向右滚动以查看 gmtoffset 值):
Test with timelocalisdst is [0]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [0] zone [EST] gmtoff [-18000]isdst is [1]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [0] zone [EST] gmtoff [-18000]isdst is [-1]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [0] zone [EST] gmtoff [-18000]Test with mktimeisdst is [0]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [0] zone [EST] gmtoff [-18000]isdst is [1]tm: sec [0] min [30] hour [0] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [0] zone [EST] gmtoff [-18000]isdst is [-1]tm: sec [0] min [30] hour [1] mday [30] mon [10] year [2005] wday [1] yday [303] isdst [0] zone [EST] gmtoff [-18000]
在我看来,他们俩都错了。 tm_isdst
字段似乎对 tm_gmtoff
字段没有影响。使用 mktime
时,tm_hour
输出发生变化,但偏移量仍然错误。
如果您将tm_mday
更改为提前几天或几天后,gmtoffset根本不会改变,这让我感到困惑。
我做错了什么或者我误解了这些函数的工作原理吗?
最佳答案
UNIX 时间非常复杂。事实证明,我的错误与 struct tm 中的 tm_year 字段有关。它应该表示自 1900 年以来的年数,因此该字段中的值应该是 105 而不是 2005(例如 2005 - 1900 = 105)。现在就得出了正确的答案。
该结构的定义可以在 this very useful page. 上找到。
关于c - 为什么 timelocal 和 mktime 无法正确处理夏令时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42308930/
我想从 string 得到一个 unix 时间戳包含形式 YYYYMMDDThhmmss+TZ 的时间表示. 为此,我将字符串转换为 struct tm然后使用 mktime将其转换为unix时间戳。
这是一个 PHP 问题。当我测试这段代码时 echo date("d-m-y h:i:S"); 在我的本地服务器和我的托管网站(这两个具有不同的时区)上,它们返回不同的日期时间值,正如预期的那样。但是
我想在微 Controller 上使用 mktime(或者至少使用 32 位宽的时间戳)。我从 avr libc source files 添加了所需的文件(在 Atmel Studio 7 中,时间
我正在将 azure-sdk 用于 python,特别是 azure-servicebus 0.50.0 from azure.servicebus import QueueClient servic
我在 mktime() 中遇到了年份问题。 每次我将低于 1970 年的年份传递到 struct tm 中,然后运行 mktime() 函数来转换我的结构时,都会失败(返回 -1) 。 有人知道为
我正在开发按含义分隔字符的程序。目前我遇到了 konverzia 函数的问题。它应该在日期字符串中添加日期名称(星期三、星期四、星期五...),但它根本不在乎。日期必须类似于周三 2012-02-01
我正在尝试将以 HHMMSS.SS,DD,MM,YYYY 格式给出的时间转换为 unix 时间。问题是,然后调用 mktime,返回相同的 time_t。 ConvertTime(std::strin
我有一个日期操作类。当我尝试用相同的值初始化它时,第一个实例工作正常,但所有其他实例每次都返回不同的值。我将日期保存在 time_t DATE 变量中。 它的构造函数: CDate (int y,in
在一个简单的测试中,获取从 de Unix Epoch (01/01/1970 00:00:00 UTC) 到 2019 年 2 月 22 日的耗时(以秒为单位),它返回了大量的 1844674407
我正在尝试将一周重复添加到包含日期信息的事件结构中。我这样做是为了在某个时间之前创建一个事件的多个实例。我的 mktime 函数出现段错误,其中 full_time = mktime(&caltime
我想用澳大利亚/悉尼时区构造一个struct tm,所以我首先使用: setenv("TZ","Australia/Sydney",1); tzset() 然后我将struct tm设置为: stru
这是将 Fri Jan 1 00:00:00 IST 1970 转换为 EPOCH 的代码段 memset(&Date_st,0,sizeof(struct tm)); Date_st.tm_ye
我正在尝试将用户输入日期添加到现有时间结构中,但我收到了一个我不明白的错误。当我试图修改月份日期时,编译器告诉我工作日超出范围。代码贴在下面。 struct tm date; int m, d, y,
这个问题在这里已经有了答案: C++ mktime returning random dates (3 个答案) 关闭 6 年前。 我准备了以下结构: struct tm tDepartureTim
在尝试编写返回比给定时间少 24 小时的代码时,mktime() 显示不一致的输出。我的计算类似于:current_time(GMT) - 86400 应该返回正确的值。我们需要做的就是根据输入的时间
这个问题已经有答案了: Python | mktime overflow error (2 个回答) 已关闭 6 年前。 使用 Python 时 time模块我收到此错误: OverflowError
继续 my attempt to create a DateTime class ,我试图在我的函数中存储“纪元”时间: void DateTime::processComponents(int mo
我现在正在使用 gcc 编译器在我的 RedHat Linux 机器上编写一个 C 程序,它将接受两个日期作为输入并计算它们之间的差异。 但是,我发现 mktime() 有一个奇怪的行为,如下面的代码
我做的一个网站突然出现以下错误,到目前为止一直运行良好: A PHP Error was encountered Severity: Warning Message: mktime() [functi
我正在研究一些与时间相关的功能,我选择始终使用 UTC 时间并将时间戳存储为整数以保持一致性。 但是,我注意到当我使用mktime 时,当前设置的时区似乎对mktime 的返回值有影响。从文档中我了解
我是一名优秀的程序员,十分优秀!