我目前正在使用“ localtime_s”功能,语法如下:
errno_t localtime_s (struct tm* _tm, const time_t *time);
我发现了一些奇怪的行为。 如果我们具有智利圣地亚哥时区,则此函数针对不同的当前系统时间(在Windows“控制面板”上设置的时间),返回“ _tm”结构的不同“ tm_isdst”字段(对于相同的“ time”参数)。 >
换句话说,“ localtime_s”为我们提供了不同的系统时间(DST转换日期是“ tm_isdst”字段值为“ False”的日期和前一天)的不同DST转换日期(“时间”中传递的同一年份) “ tm_isdst”的值为“ True”,反之亦然)。
如果通过“ time”参数传递的年份与系统时间中的年份相同,则总是正确的。但是,当系统时间的年份与“时间”参数中的年份不同时,基于“ localtime_s”函数返回的“ tm_isdst”值的DST转换日期将变为错误。
示例: 智利圣地亚哥时区。 2014年(通过“时间”参数传递)。 DST的第一次转换是在4月26/27日之间。 如果当前系统时间年份也是2014,则一切正常-4月26日“ tm_isdst”为“ True”,4月27日为“ False”。 但是,如果系统时间年份为2018,则对于不等于5月10日的日期,“ tm_isdst”将为“ True”,仅从5月11日起,它将变为“ False”。这意味着“ localtime_s”函数将DST转换日期视为5月11日,这是错误的。
另一个示例,如果系统年份为2010,则“ localtime_s”的DST转换日期(2014年使用“ time”参数传递)将为4月6日。 因此,我们在同一年(但Windows中设置的不同年份)获得了不同的DST过渡日期。
我不认为这是默认行为,因为:
系统是Windows Server 2012 R2 Standart,x64。
能否请您说出导致此问题的原因?这是“ localtime_s”功能错误吗?
P.s。以下是一些来自系统年份的DST过渡日期依赖性的示例:
DST transition dates, Santiago, 2014 system time year
DST transition dates, Santiago, 2018 system time year
DST transition dates, Santiago, 2020 system time year
P.p.s。这是一个简单的示例进行测试(抱歉,在包含之前遗漏了“#”,stackoverflow不想使用该符号保存我的帖子):
include <iostream>
include <time.h>
int main()
{
time_t t_26_Apr = 1398517200; // 26-Apr-2014
time_t t_27_Apr = 1398517200 + 24 * 3600; // 27-Apr-2014
time_t t_10_May = 1398517200 + 14 * 24 * 3600; // 10-May-2014
time_t t_11_May = 1398517200 + 15 * 24 * 3600; // 11-May-2014
tm tm_26_Apr;
tm tm_27_Apr;
tm tm_10_May;
tm tm_11_May;
localtime_s(&tm_26_Apr, &t_26_Apr);
localtime_s(&tm_27_Apr, &t_27_Apr);
localtime_s(&tm_10_May, &t_10_May);
localtime_s(&tm_11_May, &t_11_May);
std::cout << "26-Apr-2014 DST status is:\t" << tm_26_Apr.tm_isdst << std::endl;
std::cout << "27-Apr-2014 DST status is:\t" << tm_27_Apr.tm_isdst << std::endl;
std::cout << "10-May-2014 DST status is:\t" << tm_10_May.tm_isdst << std::endl;
std::cout << "11-May-2014 DST status is:\t" << tm_11_May.tm_isdst << std::endl;
return 0;
}
2014年圣地亚哥实际DST转换日期为4月26/27日午夜。但是如果Windows系统时间年份为2018,过渡日期为5月10/11。我在2个不同的操作系统(Windows 10和Windows Server 2012 R2)和2个不同的计算机上对此进行了测试,并得到了相同的结果。
答案 0 :(得分:0)
确实看起来很奇怪。在Windows 10上,我检查了圣地亚哥的日期。 2014年和2016年的夏令时日期不同。 2015年完全没有信息(该年可能没有夏令时),这些日期会随着时间的变化而变化。对于美国和加拿大的大部分地区,这种情况在2007年也发生了变化。夏令时的概念一开始就毫无用处,各国政府经常无缘无故地采用这种做法。除了依赖操作系统之外,您无能为力。尽可能使用UTC在内部存储时间,然后转换为本地时间以进行输出。
#include <stdio.h>
#include <Windows.h>
int main()
{
for(int year = 2014; year < 2020; year++)
{
TIME_ZONE_INFORMATION tz;
GetTimeZoneInformationForYear((USHORT)year, NULL, &tz);
printf("Year %d, bias: %d\n", year, tz.Bias);
printf("Standard: %02d/%02d %02d:%02d\n",
tz.StandardDate.wMonth, tz.StandardDate.wDay,
tz.StandardDate.wHour, tz.StandardDate.wMinute);
printf("Daylight: %02d/%02d %02d:%02d\n\n",
tz.DaylightDate.wMonth, tz.StandardDate.wDay,
tz.DaylightDate.wHour, tz.DaylightDate.wMinute);
}
return 0;
}
输出:
Year 2014, bias: 240
Standard: 04/05 23:59
Daylight: 09/05 23:59
Year 2015, bias: 180
Standard: 00/00 00:00
Daylight: 00/00 00:00
Year 2016, bias: 240
Standard: 05/02 23:59
Daylight: 08/02 23:59
Year 2017, bias: 240
Standard: 05/02 23:59
Daylight: 08/02 23:59
Year 2018, bias: 240
Standard: 05/02 23:59
Daylight: 08/02 23:59
Year 2019, bias: 240
Standard: 05/02 23:59
Daylight: 08/02 23:59