使用标准库构建/解析UTC日期

时间:2016-01-13 20:58:48

标签: c++ datetime

我在使用标准库在c ++中构建 UTC 日期时遇到了麻烦。 例如(任何都可以):

  • 从包含日月年的单独变量构建......

或解析

  •   

    01/01/1970 00:00:00 UTC

  •   

    01/01/1970 00:00:00 +0000

  •   

    01/01/1970 00:00:00#(隐含在UTC中)

条件:

  • 不需要解释时区字符串,但我需要确保日期被解释为UTC。
  • 日期始终正确格式化
  • 任何格式都可以接受,只要它能完成工作
  • 应该是可移植的(UNIX变种和Windows)
  • 尽可能避免使用外部库

目前最好的候选人是:

  • std::time_get但规范没有说明时区(我理解的是:-))。
  • 提升的date_time,但它是一个相当重的依赖(在C++ library (unix) to parse date/time string Including timezones中提到,但答案早于C ++ 11)
  • unix strptime在Windows上无法移植
  • 直接使用std::tm,但在我的系统(glibc)上,它有非标准的未记录字段(即tm_zone ...)。我想我可以用gmtime(0)初始化它,然后修改日,月,年字段。

如何从UTC日期构建std::chrono::time_point::time_point

2 个答案:

答案 0 :(得分:2)

  

如何从UTC日期构建std::chrono::system_clock::time_point

就这一部分而言,here是一个仅限标题的高性能C ++ 11/14现代解决方案。它可以像这样使用:

int y = 2016;
int m = 1;
int d = 14;
int h = 18;
int min = 2;
int sec = 15;
std::chrono::system_clock::time_point tp = 
    date::sys_days{date::year{y}/m/d} +
    std::chrono::hours{h} +
    std::chrono::minutes{m} +
    std::chrono::seconds{sec};

这是github上的开源免费图书馆。这是图书馆的video presentation。该库可移植到C ++ 11和C ++ 14的所有最新实现(包括VS2013和VS2015)。它提供了比从C继承的tm更好的界面,以及更大的有效范围。它还提供了更高的性能,并且在C ++ 14中具有大量的编译时功能。它旨在成为<chrono>的简单扩展,因此可与<chrono>完全互操作。

要进行解析,请使用tz.h

  

01/01/1970 00:00:00 UTC

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

int
main()
{
    std::istringstream in{"01/01/1970 00:00:00 UTC"};
    date::sys_seconds tp;
    date::parse(in, "%d/%m/%Y %T %Z", tp);
    using namespace date;
    if (!in.fail())
        std::cout << tp << '\n';
}

在上面的代码中,sys_secondsstd::chrono::time_point<system_clock, seconds>

  

01/01/1970 00:00:00 +0000

%Z更改为%z以上。

  

01/01/1970 00:00:00

删除%Z/%z

  
      
  • 尽可能避免使用外部库
  •   

抱歉,否则你必须:

  
      
  • 直接搞乱std :: tm,......
  •   

此库允许您解析%z%Z。你可以扔掉缩写,或者发现它,并试着找出它的含义(通常缩写是模棱两可的)。使用%z时,偏移量将改变解析后的值,以便为您提供UTC:

std::istringstream in{"01/01/1970 00:00:00 +0500"};
date::sys_seconds tp;
date::parse(in, "%d/%m/%Y %T %z", tp);
using namespace date;
if (!in.fail())
    std::cout << tp << '\n';

输出:

1969-12-31 19:00:00

如果您希望获得当地时间,那也很容易:

std::istringstream in{"01/01/1970 00:00:00 +0500"};
date::local_seconds tp;
date::parse(in, "%d/%m/%Y %T %z", tp);
using namespace date;
if (!in.fail())
    std::cout << tp << '\n';

输出:

1970-01-01 00:00:00

local_secondsstd::chrono::time_point,但基于没有now()的“时钟”。

答案 1 :(得分:0)

更好地使用std::tm ......因为它是标准的。

不要担心tm_zone。它是一个可选字段,仅在某些环境中可用,如Linux / GNU或freeBSD ......(实际上,正如你所指出的那样,它带有glibc)。

然而, NO 功能效果。 使用它的程序应该有#ifndef#ifdef指令来嵌入语句,允许在没有结构中定义字段的系统上进行编译。

回答你的上一个问题......不确定你的需求,但一个起点可以是:

system_clock::time_point tp = system_clock::now();

在这里找到:

http://www.cplusplus.com/reference/chrono/time_point/time_since_epoch/

希望它有所帮助,

PS :请注意:Difference between steady_clock vs system_clock?