使用C++的日期库读取时间
Using C++'s date library to read times
我正试图使用Howard Hinnant的日期库(https://github.com/HowardHinnant/date)将用户输入读取到日期时间对象中。我想使用这个库,因为它是现代的,并且将包含在C++20中。
程序应该能够接受ISO 8601格式的日期时间(YYYY-MM-DDTHH:MM:SS+HHMM
等,如2020-07-07T18:30+0100
(以及DD-MM HH:MM
或HH:MM
格式的简单日期时间。在第二种情况下,应该假设缺失的信息将用当前日期/年份填写(时区将稍后处理(。
这是我的尝试。
using namespace date;
int main(int argc, char ** argv)
{
std::istringstream ss { argv[1] };
std::chrono::system_clock::time_point dt
{ std::chrono::system_clock::now() };
if ( date::from_stream(ss, "%F T %T %z", dt) ) {
std::cout << "Cond 1 enteredn";
}
else if ( ss.clear(), ss.seekg(0); date::from_stream(ss, "%d-%m %R", dt)) {
std::cout << "Cond 2 enteredn";
}
std::cout << dt << "n";
}
对于第一种格式,它可以按预期工作:
./a.out 2020-06-07T18:30:00+0200
Cond 1 entered
2020-06-07 16:30:00.000000000
然而,第二个方法返回一些奇怪的东西,这取决于所使用的编译器。使用GCC和-std=c++17/-std=c++2a
:编译时
./a.out "07-08 15:00"
Cond 2 entered
1754-04-06 13:43:41.128654848
编辑2:使用LLVM和-std=c++2a
:编译时
./a.out "07-08 15:00"
Cond 2 entered
0000-08-07 15:00:00.000000
这与我的预期有点接近。不过,我宁愿不让这种行为依赖于所使用的编译器!
我真的被这里发生的事情难住了,而且我似乎对文档一头雾水。如何让date::from_stream
简单地覆盖时间和日期,并保留其他内容?
编辑1:
为了清楚起见,我(错误地(认为当输入第二个条件时,会保留当前年份,因为time_point
对象是用当前年份初始化的。例如,在第二个示例中,我希望对from_stream
的第二次调用将time_point
对象保留为2020-08-07 15:00:33.803726000
。请参阅评论以了解更多信息。
编辑2:
添加了尝试使用不同编译器的结果。
好问题!!!
您做得不太好,和您在date.h!:-(中发现了一个错误
首先,我已经修复了你在这里遇到的错误。问题是我在from_stream
中的not_a_year
值错误,这个错误已经隐藏了好几年了!非常感谢你帮我找到它!要更新,只需拉动主分支的顶端。
当您的程序使用参数为"07-08 15:00"
的固定日期.h运行时,它既不输入任何条件,也不打印出当前时间。
说明:
from_stream(stream, fmt, x)
的语义是,如果stream
不包含足够的信息来使用fmt
完全指定x
,则设置stream.failbit
,而不修改x
。而CCD_ 21并没有完全指定一个CCD_。
date.h中的错误是date.h未能识别出没有足够的信息来完全指定system_clock::time_point
,并正在向其写入确定性垃圾。由于system_clock::time_point
的精度不同(microseconds
与nanoseconds
(,该垃圾碰巧在LLVM/libc++和gcc上产生了两个不同的值。
通过修复错误,解析会彻底失败,因此不会写入垃圾。
我相信你的下一个问题是:
如何进行第二次解析?
int main(int argc, char ** argv)
{
std::istringstream ss { argv[1] };
auto dt = std::chrono::system_clock::now();
ss >> date::parse("%FT%T%z", dt);
if (!ss.fail())
{
std::cout << "Cond 1 enteredn";
}
else
{
ss.clear();
ss.seekg(0);
date::month_day md;
std::chrono::minutes hm;
ss >> date::parse("%d-%m", md) >> date::parse(" %R", hm);
if (!ss.fail())
{
std::cout << "Cond 2 enteredn";
using namespace date;
auto y = year_month_day{floor<days>(dt)}.year();
dt = sys_days{y/md} + hm;
}
}
std::cout << dt << "n";
}
第一次解析与您所做的一样,只是我将parse
的使用切换为from_stream
,后者是一个更高级别的API。这对于第一次解析来说并不重要,但会使第二次解析更加整洁。
对于第二个解析,您需要解析两个项目:
month_day
- 一天中的某个时间
然后将这两个元素与当前的year
组合以产生所需的time_point
。
现在,每个解析都完全指定了它从流中解析的变量。
你最初犯的错误是想象有一个";年份字段";在CCD_ 32的掩护下。实际上,自1970-01-01 00:00:00 UTC以来,这个数据结构只不过是微秒或纳秒(或其他(的计数。所以第二个解析必须:
- 分析字段,然后
- 将
time_point
分解为字段以获得当前年份,然后 - 将字段重新组合到
time_point
中
- 从文本文件中读取时钟时间和事件时间并进行处理
- 使用C++的日期库读取时间
- 读取悖论时间戳字段
- 如何在 Windows 上的 C++ 中根据文件的修改时间读取目录中的文件
- 用FFMPEG读取每帧时间码
- C++-需要读取存储在文件(.txt)中的时间戳并正确检索
- 读取串行命令花费太多时间
- 从C 中的GMT读取时间
- 程序读取文字或解释变量所需的时间是否更少
- C++:读取.BMP文件时出现问题;文件结束时间早于预期
- 在编译时间之前抓取常数值
- 如何在C 中读取具有前缀和时间戳为文件名的文件
- 测量 l1/l2 缓存中加载的用于读取(包括预取)的行数
- 从文件读取/写入时出现内存和时间问题
- 随着时间的流逝,C 会减慢读取70,000个文件
- 如何读取时间输入并格式化输出
- 如何读取特定单词的字符串并计算发现的时间
- C++ 模板复杂图像读取类执行时间慢,声明和实现分离
- Boost.python 将对象拉取到本地范围内以进行读取访问
- 如何在QTimeEdit中读取当前时间