c - localtime_s取决于智利圣地亚哥时区的当前系统时间

标签 c windows localtime

我目前正在使用“localtime_s”函数,语法如下:

errno_t localtime_s (struct tm* _tm, const time_t *time);

我发现了一些奇怪的行为。 如果我们有智利、圣地亚哥时区,则对于不同的当前系统时间(在 Windows 控制面板上设置的时间),此函数返回“_tm”结构的不同“tm_isdst”字段(对于相同的“time”参数)。

换句话说,“localtime_s”为不同的系统时间提供了不同的 DST 转换日期(对于在“time”中传递的同一年)(DST 转换日期是“tm_isdst”字段值为“False”的日期和前一天) “tm_isdst”值为“True”,反之亦然)。

如果使用“time”参数传递的年份与系统时间中的年份相同,则总是正确的。但是,当系统时间的年份与“time”参数中的年份不同时,基于“localtime_s”函数返回的“tm_isdst”值的夏令时转换日期就会出错。

示例: 圣地亚哥,智利时区。 2014 年(通过“时间”参数)。第一次 DST 转换发生在 4 月 26 日至 27 日之间。 如果当前系统时间年份也是 2014 年,则一切正常 - “tm_isdst”对于 4 月 26 日为“True”,对于 4 月 27 日为“False”。 但如果系统时间年份是 2018 年,则对于小于 5 月 10 日的日期,“tm_isdst”将为“True”,并且仅从 5 月 11 日开始,它才变为“False”。这意味着“localtime_s”函数将 DST 转换日期视为 5 月 11 日,这是错误的。

另一个例子,如果系统年份是 2010 年,则来自“localtime_s”的 DST 转换日期(对于通过“time”参数传递的 2014 年)将为 4 月 6 日。 因此,我们在同一年获得了不同的 DST 过渡日期(但在 Windows 中设置了不同的年份)。

我不认为这是默认行为,因为:

  1. 我尝试在 google 上搜索“localtime_s”函数,但没有找到任何有关当前系统时间依赖性的信息,特别是在函数描述中。
  2. 我测试了其他时区的“localtime_s”(例如 UTC-8 太平洋时间(美国和加拿大)和 UTC+2 赫尔辛基、基辅、里加、索非亚、塔林、维尔纽斯),它与它们配合良好 - DST 过渡日期不依赖于当前系统时间。
  3. 我在 Linux 上测试了相同的“localtime_r”函数,它运行良好 - DST 转换日期也不依赖于当前系统时间(也适用于圣地亚哥时区)。
  4. 如果 Windows 系统时间为 2015 年,“lolaltime_s”函数会认为我们根本没有任何年份的 DST 转换(“tm_isdst”对于任何时间和任何年份始终为“True”)。从我的角度来看,这显然是错误的。

系统是 Windows Server 2012 R2 Standard,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 日。我在 2 个不同的操作系统(Windows 10 和 Windows Server 2012 R2)和 2 台不同的计算机上对此进行了测试,并得到了相同的结果。

最佳答案

看起来确实很奇怪。在 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

关于c - localtime_s取决于智利圣地亚哥时区的当前系统时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51368350/

相关文章:

c# - 从服务器获取当前日期时间并在 C# 中将其转换为本地时间

java - 如何区分两个 JodaTime LocalTime 时间戳?

windows - Win7 : Get microphone mute status

c - 使用 -g、-ggdb、-g3 或 -ggdb3 时,GCC 不会生成调试器信息

c - 使用 strtok 解析字符串数组

c - 在 C 中处理包含多个 Null 字符的字符串

windows - 在 Windows 上应用补丁的好 GUI 实用程序是什么?

windows - 从 CMD %CD% 输出中删除感叹号 (!)

java - 在java中格式化本地时间

c++ - (c/c++) 试图强制 EOF 从父进程发送输入到子进程