假设我给了一个字符串,如:"2009-4-9"
,意思是2009年4月9日。假设对于初学者,我只关心当地时间(我也关注其他时区,但我先解决这个简单的问题。了解夏令时是否在当时生效的最佳方式是什么?
您可以假设系统具有正确更新的时区文件,例如/etc/localtime
,我对便携式解决方案感兴趣。 c或c ++也是可以接受的。
你也可以假设我只关心过去或现在的日期,而不关心未来。
目前我有一个“黑客”看起来像这样(我知道localtime_r是一个库扩展,但它足够接近我可以使其移植的相同功能)
struct tm tm;
// convert the time string to a broken down structure in localtime
if(strptime("2009-4-9", "%Y-%m-%d", &tm)) {
// convert the broken down structure into seconds since epoch
const time_t t = mktime(&tm);
// convert it back to a broken down structure, this seems pointless at first...
// but libc will fill out fields such as tm_isdst
localtime_r(&t, &tm);
printf("DST : %d\n", tm.tm_isdst);
}
虽然这有效(并且似乎是一种非常有效的方式),但我觉得来回转换是愚蠢的。还有更好的方法吗?
答案 0 :(得分:4)
您根本不需要致电localtime_r()
。 mktime()
会将您传递的struct tm
标准化,包括将tm_isdst
设置为非负值,如果它已设置为-1
。所以你需要的只是:
struct tm tm = { 0 };
// convert the time string to a broken down structure in localtime
if(strptime("2009-4-9", "%Y-%m-%d", &tm)) {
tm.tm_isdst = -1;
// normalise the broken down structure - this calculates tm_isdst
mktime(&tm);
printf("DST : %d\n", tm.tm_isdst);
}
C标准要求mktime()
的这种行为;例如,C99说:
mktime
函数转换故障时间,表示为 当地时间,timeptr
指向日历的结构 时间值与返回值的编码相同time
函数。tm_wday
和。{的原始值 结构的tm_yday
个组件将被忽略,而原始组件则被忽略 其他组件的值不限于范围 如上所述。 276 成功完成后,其值为 设置了结构的tm_wday
和tm_yday
组件 适当地,并且其他组件被设置为代表 指定的日历时间,但其值被强制为范围 如上所述;直到tm_mday
的最终值才设置tm_mon
和tm_year
已确定。
脚注276明确指出tm_isdst
成员:
276)因此,
tm_isdst
的正值或零值会导致mktime
函数最初分别假设夏令时, 在指定时间内有效或无效。负值会导致 它试图确定夏令时是否有效 在指定的时间。
答案 1 :(得分:2)
从UTC到本地时间的转换不是可逆功能。例如,在秋天,当时钟跳回一小时,02:00和03:00之间的当地时间出现两次。如果在此时间间隔内有一段时间, 可能无法确定本地时间是在本地日光时间内的特定UTC时间发生的,还是在本地中一小时后发生的标准时间。
答案 2 :(得分:1)
我之前在C中做了很多次转换,我觉得你也很喜欢我的做法。据我所知,localtime_r及其亲属可能是你唯一的选择(除非有一些第三方日期库。)当然,Greg Hewgill对于时间切换之间的“灰色小时”是正确的。