我一直在疯狂地试图解决这个问题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
,除了需要一个时代,这让我疯了,因为如果我能得到这个时代,那么我已经得到了答案。 :(
我该如何做到这一点?
答案 0 :(得分:2)
mktime_z
将struct 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
是输入Duration
和seconds
的精细内容。如果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";
}
这会练习两次代码:
对我来说,这些都是相同的时区,导致以下输出:
2012-09-28 19:54:24 UTC
2012-09-28 19:54:24 UTC
使用此库不仅比BSD ctime API更简单,
但此API具有类型安全性。例如,UTC时间点和本地时间点由不同类型表示,允许编译器告诉您是否意外使用了错误的类型。相比之下,BSD ctime API对本地时间和UTC使用相同的类型(tm
)。