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

时间:2017-01-08 19:17:14

标签: c++ date datetime boost

我正在处理%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);
}

使用输入字符串et_time打印cet_time16:03:38.539000时,我得到了

16:03:38.539000 UTC

我在期待

  • et_timeUTC不同,因为我构建了它,提供了et_tz时区对象。
  • 当我使用cet_time构建{li> local_time_in并提供cet_tz时区对象时,
  • np.array位于不同的时区。

我做错了什么?

1 个答案:

答案 0 :(得分:2)

我不知道ec2cet的加速实施有什么问题。但是我可以很容易地用这个free, open source library来说明如何做到这一点。首先是代码,然后是逐行说明:

#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行:只需在一个地方写下格式字符串即可。 &#34;%F%T&#34;相当于&#34;%Y-%m-%d%H:%M:%S&#34;你也可以使用它。 (我懒惰)。

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

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

第7行:解析为tp

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

第10行:使用&#34; America / New_York&#34;创建zoned_time<microseconds> time_zonelocal_time tp。您可以将zoned_time简单地视为pair<time_zone, local_time>,但细节稍微复杂一些。

第11行:从zoned_time<microseconds>&#34;欧洲/巴黎&#34;创建time_zonezoned_time et_time。这会将一个本地时间转换为另一个本地时间,在此过程中等同它们的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而不是&#34; America / New_York&#34;,那么这也是第6行的单行更改(使tp sys_time<microseconds>的类型而不是{{ 1}})。