从 C++17 开始,std::chrono 除了将 time_point 转换为 time_t 并使用日期/时间格式之外,没有任何工具可以轻松地将 std::chrono::system_clock::time_point 分解为其日历日期和挂钟时间从 C 继承的功能。
可能只使用std::chrono,但并不简单。例如,这样的事情可以从std::chrono::system_clock::time_point 获取挂钟时间:
std::string time_of_day(const std::chrono::system_clock::time_point& time_point)
{
using days = std::chrono::duration<int, std::ratio<86400>>;
auto midnight = std::chrono::floor<days>(time_point);
auto time_since_midnight = time_point - midnight;
auto hours = std::chrono::floor<std::chrono::hours>(time_since_midnight);
auto minutes = std::chrono::floor<std::chrono::minutes>(time_since_midnight - hours);
auto seconds = std::chrono::floor<std::chrono::seconds>(time_since_midnight - minutes - hours);
std::ostringstream oss;
oss << hours.count() << ":" << std::setw(2) << std::setfill('0') << minutes.count() << ":" << seconds.count();
return oss.str();
}
int main() {
std::cout << time_of_day(std::chrono::system_clock::now());
}
Live Demo
这一点都不简单,我敢肯定我忽略了一些极端情况,但它只使用 std::chrono 设施。
C++20 将介绍几种更容易做到这一点的方法。在撰写本文时,尚未实现任何标准库实现。
首先,如果您想要完整的日期/时间,将会有一个重载的operator<<(std::ostream&, const std::chrono::system_clock::time_point&) 会为您格式化并打印出来:
int main() {
std::cout << std::chrono::system_clock::now();
}
如果你只想要time_point、std::chrono::day_month_year、std::chrono::time_of_day的日期或时间部分,可以用朋友来分解time_point。
例如,上面的time_of_day 函数可以更简单地像这样完成:
std::chrono::time_of_day time_of_day(const std::chrono::sytem_clock::time_point& time_point)
{
auto midnight = std::chrono::floor<std::chrono::days>(time_point);
return std::chrono::time_of_day{time_point - midnight};
}
int main() {
std::cout << time_of_day(std::chrono::system_clock::now());
}
请参阅P3055 了解更多信息。
另一种方法是新的std::format 系列函数。将有一个std::formatter specialization for std::chrono::system_clock::time_point,它可以让您使用类似strftime 的格式字符串将time_point 格式化为字符串。例如,以下输出将与前两个 time_of_day 函数非常相似(如果不相同):
int main() {
std::cout << std::format("{%T}", std::chrono::system_clock::now());
}
请参阅P0645 和P1361 了解更多信息。