【问题标题】:Why there is no inverse function for gmtime in libc?为什么libc中没有gmtime的反函数?
【发布时间】:2016-07-11 02:15:13
【问题描述】:

在 libc 中有两个函数可以将系统时间转换为日历时间 - gmtimelocaltime,但只有 localtime 具有反函数 - mktime。为什么gmtime没有反函数,如果不应该有,为什么gmtime存在?

【问题讨论】:

    标签: time posix libc


    【解决方案1】:

    我发现这段代码的工作令人满意:

    namespace std {
        time_t timegm(tm* _Tm) 
        {
            auto t = mktime(_Tm);
            return t + (mktime(localtime(&t)) - mktime(gmtime(&t)));
        }
    }
    

    通过测试:

    auto t1 = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    auto t2 = std::timegm(std::gmtime(&t1));
    EXPECT_EQ(t1, t2);
    

    【讨论】:

    • 如果mktime(localtime(&t))mktime(gmtime(&t)) 跨越夏令时变化怎么办?
    • 我不知道。这可能确实是一个未处理的极端情况。
    【解决方案2】:

    要解释gmtime()的存在,需要一些上下文:

    gmtime() 会将 时间戳 表示(自 1970-01-01 00:00:00 以来的秒数)转换为 分解时间表示(又名,struct tm),假设timestamp 时区是 UTC

    gmtime() 函数将日历时间 timep 转换为 分解的时间表示,用Coordinated Universal 表示 时间 (UTC)。当年份不适合 整数。返回值指向一个静态分配的结构 这可能会被后续调用任何日期覆盖 和时间函数。

    另一方面,localtime() 考虑了 [本地] 系统时区(包括夏令时):

    localtime() 函数将日历时间 timep 转换为 分解时间表示,相对于用户的时间表示 指定的时区。该函数的行为就像它调用了tzset(3) 和 使用有关的信息设置外部变量 tzname 当前时区、时区与Coordinated之间的区别 世界时 (UTC) 和当地标准时间(以秒为单位),以及 如果适用夏令时规则,则将日光设置为非零值 在一年中的某些时候。

    请注意,从1970-01-01 00:00:00 开始的秒数因时区而异(当1970-01-01 00:00:00 在纽约时,它显然不在例如东京)。

    mktime() 基于 [local] 系统时区将 struct tm 转换为 time_t 值(自 1970-01-01 00:00:00 以来的秒数),不应解释为inverse 任何特定函数(例如localtime()gmtime()),因为inverse 术语可能[错误地] 解释为安全的跨系统转换:

    mktime() 函数转换分解的时间结构, 表示为当地时间,以日历时间表示。这 函数忽略调用者在 tm_wday 中提供的值 和 tm_yday 字段。 tm_isdst 字段中指定的值通知 mktime() 夏令时 (DST) 是否有效 对于 tm 结构中提供的时间:正值表示 DST 已生效;

    还有一个名为 timegm() 的不可移植函数(用于 GNU 和 BSD 系统),它假定为 UTC 时区,例如 gmtime()

    参考文献

    从 Linux 手册页项目 3.74 版的部分内容中检索到块引用的文本。

    【讨论】:

    • “逆”我的意思是如果我们取某个时间戳X,那么X = mktime(localtime(X)),但是没有这样的函数F,即X = F(gmtime(X )),我的问题是为什么 libc 中不存在 F。
    • 你仍然可以使用mktime(),但是你需要在返回值中加上或减去UTC偏移量。
    • 我可以使用 localtime 代替 gmtime 以同样的方式。那为什么gmtime 存在呢?
    • 您也可以使用名为timegm()的非便携式扩展(仅在 GNU 和 BSD 系统上)
    • 顺便说一句,mktime 是否完全等同于 timelocaltimegm 会忽略本地时区吗?
    猜你喜欢
    • 2016-07-25
    • 2017-07-12
    • 2016-02-23
    • 2022-01-16
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    相关资源
    最近更新 更多