使用ctime

时间:2016-07-11 15:28:57

标签: c++ timezone ctime

我一直在疯狂地试图解决这个问题with this API

我最初的实现类似于:

// TimezonePtr is just a share_ptr to the timezone 
std::tm getGMT(const std::tm& rawtime, TimezonePtr tz)
{
    std::tm result = rawtime;
    const auto loct = mktime_z(tz.get(), &result);
    gmtime_r(&loct, &result);
    return result;
}

但是,这并没有考虑到夏令时。例如,如果我将其Sep 28 2012 15:54:24的日期提供给Sep 28 2012 20:54:24,那么这是不正确的。看起来我想使用localtime_rz,除了需要一个时代,这让我疯了,因为如果我能得到这个时代,那么我已经得到了答案。 :(

我该如何做到这一点?

2 个答案:

答案 0 :(得分:2)

mktime_zstruct tm作为其参数之一。如果您不知道DST是否对输入日期有效,您希望将tm_isdst的{​​{1}}成员设置为tm,以表示系统应该确定是否为DST当您致电-1时,该日期/时间/时区生效。

至少对我而言,这似乎工作正常(即,它正确地得出结论,至少在我的时区,DST于2012年9月生效)。

答案 1 :(得分:0)

除了Jerry Coffin的正确(和更多投票)答案外,我还想展示如何使用modern C++11/14 library(免费和开源)完成此计算。

为了使代码易于比较,我保持API相同:

template <class Duration>
auto
getGMT(date::local_time<Duration> rawtime, const date::time_zone* tz)
{
    return tz->to_sys(rawtime);
}

这会返回std::chrono::time_point<system_clock, Duration>,其中Duration是输入Durationseconds的精细内容。如果ragtime根据指示的时区没有唯一的UTC映射,则会抛出异常。如果rawtime在夏令时转换期间发生并且发生两次或根本不发生,则会发生此类事件(例如)。如果您想要“预先决定”如何将模糊和不存在的本地时间映射到UTC,则存在用于避免异常的API。

这个功能可以像这样运用:

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono_literals;
    std::cout << getGMT(local_days{sep/28/2012} + 15h + 54min + 24s,
                        current_zone()) << " UTC\n";
    std::cout << getGMT(local_days{sep/28/2012} + 15h + 54min + 24s,
                        locate_zone("America/New_York")) << " UTC\n";
}

这会练习两次代码:

  1. 使用此计算机的当前时区。
  2. 时区为“America / New_York”
  3. 对我来说,这些都是相同的时区,导致以下输出:

    2012-09-28 19:54:24 UTC
    2012-09-28 19:54:24 UTC
    

    使用此库不仅比BSD ctime API更简单, 但此API具有类型安全性。例如,UTC时间点和本地时间点由不同类型表示,允许编译器告诉您是否意外使用了错误的类型。相比之下,BSD ctime API对本地时间和UTC使用相同的类型(tm)。