如何使用 Howard Hinnant 的库将挂钟时间日期时间修改为正确的时区和夏令时时间

问题描述 投票:0回答:1

我有挂钟日期时间,没有时区或夏令时影响。左手边是我所拥有的,写手边是我需要的。 源时间 我需要的时间

  • 2021年3月14日 00:00 2021年3月14日 00:00 美国东部时间
  • 2021年3月14日 01:00 2021年3月14日 01:00 美国东部时间
  • 14-03-2021 02:00 14-03-2021 03:00 EDT --> 添加此条目的夏令时偏移量以获得正确的时间
  • 14-03-2021 03:00 14-03-2021 04:00 EDT --> 继续添加..
  • .
  • 21 年 11 月 6 日 23:00 21 年 11 月 7 日 00:00 美国东部时间
  • 21 年 11 月 7 日 00:00 21 年 11 月 7 日 01:00 EDT --> 继续添加
  • 21 年 11 月 7 日 01:00 21 年 11 月 7 日 01:00 EDT --> 不添加 dst 偏移量
  • 21 年 11 月 7 日 02:00 21 年 11 月 7 日 02:00 EST --> 直到下一个夏令时开始才添加

我需要从 2021 年 3 月 14 日凌晨 2:00 开始,对从 DST 开始到 DST 结束的所有后续时间给予夏令时效果。另外,在 11 月,我希望删除此效果,并继续保持相同的效果,直到下一个夏令时开始日期。

#include <chrono>
#include <iostream>
#include "date/tz.h"

int main() 
{
    using namespace date;
    using namespace std;
    using namespace chrono;
    auto tz = locate_zone("America/New_York");
    zoned_time zt{tz, sys_seconds{}};
    for (local_seconds tp = local_days{March/14/2021} + 0h;
         tp <= local_days{March/14/2021} + 3h; tp += 1h)
    {
        std::cout << "input time: " << tp << std::endl;
        
        zt = {zt.get_time_zone(), tp, choose::latest};
        auto utctime = zt.get_sys_time();
        auto info = zt.get_info();
        auto utcoffset = floor<seconds>(info.offset);
        auto dst_hours = std::chrono::duration_cast<std::chrono::hours>(info.save);
        auto dst_minutes = std::chrono::duration_cast<std::chrono::minutes>(info.save - dst_hours);
        auto newtime = utctime + utcoffset + dst_hours + dst_minutes;
        cout << "output time:" << newtime << endl;
    }
}

我得到的是

  • 输入时间:2021-03-14 00:00:00
  • 输出时间:2021-03-14 00:00:00
  • 输入时间:2021-03-14 01:00:00
  • 输出时间:2021-03-14 01:00:00
  • 输入时间:2021-03-14 02:00:00
  • 输出时间:2021-03-14 04:00:00
  • 输入时间:2021-03-14 03:00:00
  • 输出时间:2021-03-14 04:00:00

我想要的是

  • 输入时间:2021-03-14 00:00:00
  • 输出时间:2021-03-14 00:00:00
  • 输入时间:2021-03-14 01:00:00
  • 输出时间:2021-03-14 01:00:00
  • 输入时间:2021-03-14 02:00:00
  • 输出时间:2021-03-14 03:00:00
  • 输入时间:2021-03-14 03:00:00
  • 输出时间:2021-03-14 04:00:00

我正在尝试找出夏令时开始的确切日期和时间。在上面的代码中,当 dst 开始额外时,我们将在凌晨 2:00 进入。 我可以看到此条目(2021 年 3 月 14 日凌晨 2:00)的信息结构显示夏令时的开始和结束。但不知道如何有效地使用它。

c++ datetime
1个回答
0
投票

为了获得所需的输出,对现有代码的最小更改只是从循环中删除几乎所有内容:

#include <chrono>
#include <iostream>
#include "date/tz.h"

int main() 
{
    using namespace date;
    using namespace std;
    using namespace chrono;

    auto tz = locate_zone("America/New_York");
    zoned_time zt{tz, sys_seconds{}};
    for (local_seconds tp = local_days{March/14/2021};
         tp <= local_days{March/14/2021} + 3h; tp += 1h)
    {
        std::cout << "input time: " << tp << std::endl;
        
        zt = {zt.get_time_zone(), tp, choose::latest};
        cout << "output time:" << zt.get_local_time() << endl;
    }
}

输出:

input time: 2021-03-14 00:00:00
output time:2021-03-14 00:00:00
input time: 2021-03-14 01:00:00
output time:2021-03-14 01:00:00
input time: 2021-03-14 02:00:00
output time:2021-03-14 03:00:00
input time: 2021-03-14 03:00:00
output time:2021-03-14 03:00:00

图书馆会为您进行计算。 无需手动检索 UTC 偏移量和额外的 DST 偏移量。 事实上,当 DST 未生效时,

save
字段甚至无法保证其准确性;当 DST 生效时,
not
0min
在问题的第一部分中,您暗示您可能也需要时区缩写。  最简单的方法是输出 

0min

来代替

zt
。 这将同时打印出来,但带有缩写:
zt.get_local_time()

输出:

cout << "output time:" << zt << endl;

无论哪种方式,这个程序都“非常接近”恒等操作。  输入的内容输出,
除了

在夏令时开始时: input time: 2021-03-14 00:00:00 output time:2021-03-14 00:00:00 EST input time: 2021-03-14 01:00:00 output time:2021-03-14 01:00:00 EST input time: 2021-03-14 02:00:00 output time:2021-03-14 03:00:00 EDT input time: 2021-03-14 03:00:00 output time:2021-03-14 03:00:00 EDT 这个当地时间实际上并不存在。 通常这一行会抛出这样的输入异常:

input time: 2021-03-14 02:00:00

但是由于

zt = {zt.get_time_zone(), tp, choose::latest}; nonexistent_local_time: 2021-03-14 02:00:00 is in a gap between 2021-03-14 02:00:00 EST and 2021-03-14 03:00:00 EDT which are both equivalent to 2021-03-14 07:00:00 UTC
,程序将不存在的 local_time 
choose::latest

映射到

2021-03-14 02:00:00
,然后在打印输出时将其映射回现有(和等效的)
2021-03-14 07:00:00 UTC
local_time
当 DST 结束时,将有两个本地凌晨 1 点时间点,
2021-03-14 03:00:00 EDT
指令将选择第二个映射(美国东部时间凌晨 1 点),而不是抛出异常。

choose::latest

    

© www.soinside.com 2019 - 2024. All rights reserved.