如何使用 std::chrono 从纪元时间中提取时间单位?

问题描述 投票:0回答:1

我从 API 中获取

ms
中的纪元时间,并希望从中提取年、月等(还比较两个日期,添加小时/天/月等)。

我看过 Howard Hinnant “计时教程” 并尝试过 cppreference,但我无法完全让它发挥作用。

这是我迄今为止所拥有的一切:

enum class DatePrecision { YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLI };
long long et = 1693322440062;
std::chrono::milliseconds ms{ et };
std::chrono::time_point<std::chrono::system_clock> tp(ms);

int getTimeUnit(const std::chrono::time_point tp, const DatePrecision dp) { 
  /* .?. */ 
}

我该去哪里?

tp
只为我提供
time_since_epoch
作为其上的函数,正如我所说,我无法从 cppreference 获取示例来工作,特别是在使用
utc_time
而不是
system_time
时。提取是/月/日将是一个很好的开始,但我更喜欢

提前感谢您的帮助!

c++ epoch c++-chrono
1个回答
0
投票

所以这很容易做到,但我不推荐这样做。我不推荐它的原因是最好留在 chrono 类型系统内,以便编译器可以帮助您在编译时找到任何逻辑错误。将这些值作为 int 返回会消除 chrono 为您提供的类型安全性。

好了,讲座就到这里了。以下是在 C++20 中执行此操作的方法(假设您的供应商已实现 C++20 的所有 chrono 部分):

#include <chrono> #include <iostream> #include <stdexcept> enum class DatePrecision { YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLI }; int getTimeUnit(const std::chrono::system_clock::time_point tp, const DatePrecision dp) { using namespace std; using namespace std::chrono; switch (dp) { case DatePrecision::YEAR: return int{year_month_day{floor<days>(tp)}.year()}; case DatePrecision::MONTH: return unsigned{year_month_day{floor<days>(tp)}.month()}; case DatePrecision::DAY: return unsigned{year_month_day{floor<days>(tp)}.day()}; default: { hh_mm_ss hms{floor<milliseconds>(tp - floor<days>(tp))}; switch (dp) { case DatePrecision::HOUR: return hms.hours().count(); case DatePrecision::MINUTE: return hms.minutes().count(); case DatePrecision::SECOND: return hms.seconds().count(); case DatePrecision::MILLI: return hms.subseconds().count(); default: throw logic_error("oops"); } } } } int main() { using namespace std; using namespace std::chrono; long long et = 1693322440062; std::chrono::milliseconds ms{ et }; std::chrono::time_point<std::chrono::system_clock> tp(ms); cout << tp << '\n'; cout << getTimeUnit(tp, DatePrecision::YEAR) << '\n'; cout << getTimeUnit(tp, DatePrecision::MONTH) << '\n'; cout << getTimeUnit(tp, DatePrecision::DAY) << '\n'; cout << getTimeUnit(tp, DatePrecision::HOUR) << '\n'; cout << getTimeUnit(tp, DatePrecision::MINUTE) << '\n'; cout << getTimeUnit(tp, DatePrecision::SECOND) << '\n'; cout << getTimeUnit(tp, DatePrecision::MILLI) << '\n'; }

输出:

2023-08-29 15:20:40.062000 2023 8 29 15 20 40 62

说明:

您需要打开每个所需的字段以获得正确的语法,以从

time_point

中提取它。请注意,

std::chrono::time_point
是模板,而不是类型。我以为您的意思是
std::chrono::system_clock::time_point
签名中的
std::chrono::time_point<std::chrono::system_clock>
(或等效的
getTimeUnit
)。
另请注意,基于 

time_point

system_clock
具有 UTC 语义,而不是当地时间。
对于“日期字段”,首先使用 

time_point

days
截断为
floor<days>
精度,然后将其转换为
year_month_day
year_month_day
类型具有
year
month
day
的 getter,它们随后会显式转换为整型。
对于“一天中的时间字段”,从原始值中减去日期精度

time_point

,即可得到一天中的时间作为持续时间。然后类型

hh_mm_ss
duration
转换为
{hours, minutes, seconds, subseconds}
数据结构,每个字段都有 getter。
如果您没有可用的 C++20 chrono 位,您仍然可以通过利用我的

免费、开源、仅限头文件的 C++20 chrono 预览库

来使用此代码。 只需在适当的地方添加

#include "date/date.h"

using namespace date;
即可,其余语法相同。当您能够迁移到 C++20 时,这显然会很容易地移植到它。
免责声明:我把它放在一起,它可能可以重构得更整洁一些。但希望这能让你开始。

© www.soinside.com 2019 - 2024. All rights reserved.