使用标准库生成/解析UTC日期
Build/parse UTC date using standard library
我在c++中使用标准库构建UTC日期时遇到问题。例如(任何都可以):
- 从包含年月日的单独变量构建
或解析
-
1970年1月1日00:00:00 UTC
-
1970年1月1日00:00:00+0000
-
1970年1月1日00:00:00#(隐含UTC)
条件:
- 时区字符串不需要解释,但我需要确保日期被解释为UTC
- 日期的格式总是正确的
- 只要完成工作,任何格式都可以接受
- 应该是可移植的(UNIX变体和Windows)
- 尽可能避免使用外部库
到目前为止最好的候选者是:
std::time_get
,但规范没有说明任何关于时区的内容(据我所知:-)- boost的
date_time
,但它是一个相当严重的依赖项(在C++库(unix)中提到解析日期/时间字符串包括时区,但答案早于C++11) - unix
strptime
在windows上不可移植 - 直接使用
std::tm
,但在我的系统(glibc)上,它有非标准的未记录字段(即tm_zone…)。我想我可以用gmtime(0)
初始化它,然后修改天、月、年字段
如何从UTC日期构建std::chrono::time_point::time_point
?
如何从UTC日期构建
std::chrono::system_clock::time_point
?
就这一部分而言,这里有一个仅限标头的高性能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上的一个开源免费库。这是图书馆的视频演示。此库可移植到C++11和C++14的所有最新实现(包括VS2013和VS2015)。它提供了比继承自C的tm
更好的接口,并且具有更大的有效性范围。它还提供了更高的性能,以及C++14中大量的编译时能力。它被设计为<chrono>
的简单扩展,因此可以与<chrono>
完全互操作。
对于解析,请使用tz.h:
1970年1月1日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_seconds
是std::chrono::time_point<system_clock, seconds>
。
1970年1月1日00:00:00+0000
将上面的%Z
更改为%z
。
1970年1月1日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_seconds
是std::chrono::time_point
,但基于没有now()
的"时钟"。
更好地使用std::tm
。。。因为这是标准的。
不要担心tm_zone。这是一个可选字段,仅在Linux/NGNU或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:关注以下内容:steady_clock和system_clock之间的区别?
- 继承函数的重载解析
- 基类中的函数名称解析
- 提升精神:解析布尔表达式并简化为规范范式
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- gcc和c++17的过载解析失败
- Log4cpp:以UTC/GMT时区打印日期
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- C++:floor unix时间戳到UTC月份
- 构造函数和转换运算符之间的重载解析
- 未解析的外部符号_MsiLocateComponentW@12.
- '尝试解析可变参数模板时无法推断出'T的模板参数
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- C++的解析器在可以区分比较和模板实例化之前会做什么?
- std::strftime 在 Windows 中使用 GMTIME 将时区 UTC 显示为 UTC+1
- 如何在 cpp 中解析此文件?
- 在C++中使用 gRPC 时未解析的外部符号
- IDE (CLion) 无法解析C++模板类型
- 配置文件解析器仅返回以前的值
- 增强精神解析器规则以检测语句中的特殊结尾
- 使用标准库生成/解析UTC日期