繁体   English   中英

来自 `std::string` 的 `boost::local_time::date_time`

[英]`boost::local_time::date_time` from `std::string`

我正在使用%Y-%m-%d %H:%M:%S%f格式的日期/时间字符串。

我想设计一个函数,该函数采用America/New_York时区中的日期/时间字符串并返回Europe/Paris时区中的日期/时间字符串。

我想出了以下内容

std::string ec2cet(const std::string &date_time_str)
{
  using namespace boost::posix_time;
  using namespace boost::gregorian;
  using namespace boost::local_time;

  tz_database tz_db;
  time_zone_ptr et_tz = tz_db.time_zone_from_region("America/New_York");
  time_zone_ptr cet_tz = tz_db.time_zone_from_region("Europe/Paris");

  ptime absolute_time = time_from_string(date_time_str);
  local_date_time ec_time(absolute_time, et_tz);
  local_date_time cet_time = et_time.local_time_in(cet_tz);

  return to_simple_string(cet_time);
}

当使用输入字符串16:03:38.539000打印et_timecet_time ,我得到

16:03:38.539000 UTC

我期待

  • et_timeUTC不同,因为我构造它提供了et_tz时区对象。
  • cet_time处于不同的时区,因为我使用local_time_in构建它并提供了cet_tz时区对象。

我究竟做错了什么?

我不知道ec2cet的 boost 实现有ec2cet 但是,我可以很容易地展示如何使用这个免费的开源库来做到这一点。 先上代码,再逐行解释:

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

std::string
ec2cet(const std::string& date_time_str)
{
    using namespace std;                                 //  1
    using namespace std::chrono;                         //  2
    using namespace date;                                //  3
    constexpr auto fmt = "%F %T";                        //  4
    istringstream in{date_time_str};                     //  5
    local_time<microseconds> tp;                         //  6
    in >> parse(fmt, tp);                                //  7
    if (in.fail())                                       //  8
        return std::string{};                            //  9
    auto et_time  = make_zoned("America/New_York", tp);  // 10
    auto cet_time = make_zoned("Europe/Paris", et_time); // 11
    cout << "et_time  = " << et_time << '\n';            // 12
    cout << "cet_time = " << cet_time << '\n';           // 13
    return format(fmt, cet_time);                        // 14
}

第 1-3 行只是将所有内容都带入了本地空间,所以事情就不是那么冗长了。

第 4 行:只需将格式字符串写在一处。 “%F %T”相当于“%Y-%m-%d %H:%M:%S”,你也可以使用它。 (我很懒)。

第 5 行:该库将解析出任何流,因此我们需要将输入字符串date_time_str转换为流( in )。

第 6 行:您说已知输入字符串表示“America/New_York”中的本地日期/时间。 local_time<microseconds> chrono::time_point local_time<microseconds>类型是一个chrono::time_point ,它可以将任何时区的本地时间表示为微秒精度。 这个( tp )的一个实例是我们将date_time_str解析成的。

第 7 行:解析为tp

第 8-9 行:检查解析错误。

第 10 行:使用 "America/New_York" time_zonelocal_time tp创建zoned_time<microseconds> 您可以将zoned_time视为简单的pair<time_zone, local_time>尽管细节比这稍微复杂一些。

第 11 行:从time_zone "Europe/Paris" 和zoned_time et_time创建一个zoned_time<microseconds> 这会将一个本地时间转换为另一个本地时间,在此过程中将它们的 UTC 等效时间等同起来。

第 12-13 行:输出这些中间结果(用于调试目的的et_timecet_time )。

第 14 行:将cet_time格式化为所需的std::string并返回。

使用以下驱动程序运行它:

int
main()
{
    auto s = ec2cet("2017-01-08 16:03:38.539000");
    std::cout << "ec2cet   = " << s << '\n';
}

输出:

et_time  = 2017-01-08 16:03:38.539000 EST
cet_time = 2017-01-08 22:03:38.539000 CET
ec2cet   = 2017-01-08 22:03:38.539000

该程序跟踪当前的 IANA 时区数据库,并将正确遵循 IANA 数据库完整历史记录的时区规则,这两个时区从 1800 年代后期开始。

如果microseconds精度不是您想要的,您可以更改它(在第 6 行的一个地方)。 如果输入字符串应该是 UTC 而不是“America/New_York”,这也是第 6 行的一行更改(将类型sys_time<microseconds> tp sys_time<microseconds>而不是local_time<microseconds> sys_time<microseconds> local_time<microseconds> )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM