- 1 Improving the print
- 2 Getting time in my current time zone 获取我当前时区的时间
- 3 Daylight saving time 夏令时
- 4 Summary
本文为摘录,原文为: https://www.cppstories.com/2024/chrono_dates_zones/
在这篇博客文章中,我们将探讨如何使用 std::chrono 处理日期,包括时区。我们将利用该库的最新特性来检索各个时区的当前时间,同时考虑夏令时的变化。此外,我们还将结合 C++23 中引入的新功能,例如增强的打印函数等。
让我们从以下代码开始,它将打印当前的日期和时间:
#include <chrono>
#include <print>
int main() {
auto now = std::chrono::system_clock::now();
std::print("now is {}", now);
}
在我的会话中,我得到以下结果:
Now is 2024-11-01 11:44:06.374573703
这很简单,但我们处于哪个时区?我们可以以更短的形式打印出来吗?我们如何检查世界各地的时间?夏令时呢?
第一件事:时间输出。
1 Improving the print
如您所见,我使用了 C++23 中的 std::print
,这在 GCC 14 中可用!默认情况下,
使用 std::chrono::system_clock::now()
获得的时间点会打印完整信息,
但我们可以更改并调整它。例如:
基本日期和时间格式设置 Basic Date and Time Formatting
- 仅显示日期:
{0:%F}
将日期格式化为YYYY-MM-DD
。 - 使用 hh:mm:ss 格式显示时间:
{0:%T}
将时间格式化为HH:MM:SS
。 - 显示月份和/或星期几的名称:
{0:%A, %B}
将格式化为星期几,月份。
- 仅显示日期:
Advanced Formatting Options
Year and Month:
{0:%Y}
: Full year (e.g., 2024).{0:%y}
: Last two digits of the year (e.g., 24).{0:%B}
: Full month name (e.g., November).{0:%b}
: Abbreviated month name (e.g., Nov).
Day and Week:
{0:%d}
: Day of the month, zero-padded (e.g., 01).{0:%A}
: Full weekday name (e.g., Friday).{0:%a}
: Abbreviated weekday name (e.g., Fri).
Time of Day:
{0:%H}
: Hour (24-hour clock), zero-padded (e.g., 14).{0:%I}
: Hour (12-hour clock), zero-padded (e.g., 02).{0:%M}
: Minute, zero-padded (e.g., 05).{0:%S}
: Second, zero-padded (e.g., 09).{0:%p}
: AM/PM designation.
Time Zone:
{0:%Z}
: Time zone abbreviation (e.g., UTC).{0:%z}
: Offset from UTC (e.g., +0000).
Here is an example demonstrating some of these formatting options:
#include <chrono>
#include <print>
int main() {
auto now = std::chrono::system_clock::now();
std::print("Full date and time: {0:%Y-%m-%d %H:%M:%S}\n", now);
std::print("Date only: {0:%F}\n", now);
std::print("Time only: {0:%T}\n", now);
std::print("Day of the week: {0:%A}\n", now);
std::print("Month name: {0:%B}\n", now);
std::print("12-hour clock with AM/PM: {0:%I:%M:%S %p}\n", now);
std::print("ISO 8601 format: {0:%FT%T%z}\n", now);
}
Run @Compiler Explorer
Example output:
Full date and time: 2024-11-02 19:35:16.296643881
Date only: 2024-11-02
Time only: 19:35:16.296643881
Day of the week: Saturday
Month name: November
12-hour clock with AM/PM: 07:35:16.296643881 PM
ISO 8601 format: 2024-11-02T19:35:16.296643881+0000
2 Getting time in my current time zone 获取我当前时区的时间
#include <chrono>
#include <print>
int main() {
const auto now = std::chrono::system_clock::now();
auto zt_local = std::chrono::zoned_time{ std::chrono::current_zone(), now };
std::print("now is {} UTC and local is: {}\n", now, zt_local);
constexpr std::string_view Warsaw{ "Europe/Warsaw" };
constexpr std::string_view NewYork{ "America/New_York" };
constexpr std::string_view Tokyo{ "Asia/Tokyo" };
try
{
const std::chrono::zoned_time zt_w{Warsaw, now};
std::print("Warsaw: {0:%F} {0:%R}\n", zt_w);
const std::chrono::zoned_time zt_ny{NewYork, now};
std::print("New York: {0:%F} {0:%R}\n", zt_ny);
const std::chrono::zoned_time zt_t{Tokyo, now};
std::print("Tokyo: {0:%F} {0:%R}\n", zt_t);
}
catch (std::runtime_error& ex)
{
std::print("Error: {}", ex.what());
}
}
Example output:
now is 2024-11-01 19:24:51.319170338 UTC and local is: 2024-11-01 19:24:51.319170338
Warsaw: 2024-11-01 20:24
New York: 2024-11-01 15:24
Tokyo: 2024-11-02 04:24
让我们现在深入细节:
获取当前时间:
- 我们通过使用
std::chrono::system_clock::now()
来获取当前时间。 这将给我们 UTC 的当前时间。
- 我们通过使用
本地时区:
- 我们使用
std::chrono::current_zone()
创建一个std::chrono::zoned_time
对象, 该对象会自动检测代码运行所在系统的本地时区。这使我们能够将 UTC 时间转换为本地时区。
- 我们使用
时区转换:
我们使用 std=::string_view= 定义三个时区:华沙、纽约和东京。 这些时区是使用各自的 IANA 时区标识符进行指定的。
对于每个时区,我们创建一个
std::chrono::zoned_time
对象, 将当前的 UTC 时间转换为指定的时区。
打印结果:
我们使用
std::print
来显示 UTC 和本地时区的当前时间。对于每个指定的时区(华沙、纽约、东京), 我们使用格式说明符
{0:%F}
打印日期(YYYY-MM-DD
)和{0:%R}
打印时间(HH:MM
)。
错误处理: – 代码被包裹在一个
try-catch
块中,以处理任何潜在的运行时错误,例如无效的时区标识符。
3 Daylight saving time 夏令时
我们甚至可以检查与我们当前时区相关的一些额外信息。
我们可以从 zoned_time
中获取信息并打印出开始/结束、偏移量等信息:
#include <chrono>
#include <print>
#include <iostream>
int main() {
try
{
const auto now = std::chrono::floor<std::chrono::minutes>(std::chrono::system_clock::now());
auto zt_local = std::chrono::zoned_time{ "Europe/Warsaw", now };
std::print("现在是 {} UTC,华沙是: {}\n", now, zt_local);
auto info = zt_local.get_info();
std::print("本地时间信息: \n缩写: {},\n 开始 {}, 结束 {}, \n偏移 {}, 夏令时 {}\n",
info.abbrev, info.begin, info.end, info.offset, info.save);
}
catch (std::runtime_error& ex)
{
std::print("错误: {}", ex.what());
}
}
和夏令时信息:
#include <chrono>
#include <print>
void printInfo(std::chrono::sys_days sd, std::string_view zone) {
auto zt_local = std::chrono::zoned_time{ "Europe/Warsaw", std::chrono::sys_days{sd} };
auto info = zt_local.get_info();
std::print("在 {:%F} 的 {} 的时间信息:\n缩写: {},\n开始 {}, 结束 {}, \n偏移 {}, 夏令时 {}\n",
sd, zone, info.abbrev, info.begin, info.end, info.offset, info.save);
}
int main() {
try
{
printInfo(std::chrono::year{ 2024 } / 9 / 14, "Europe/Warsaw");
printInfo(std::chrono::year{ 2024 } / 11 / 14, "Europe/Warsaw");
}
catch (std::runtime_error& ex)
{
std::print("错误: {}", ex.what());
}
}
我得到了:
在 Europe/Warsaw 的时间信息 2024-09-14:
缩写: CEST,
开始 2024-03-31 01:00:00, 结束 2024-10-27 01:00:00,
偏移 7200s, 夏令时 60min
在 Europe/Warsaw 的时间信息 2024-11-14:
缩写: CET,
开始 2024-10-27 01:00:00, 结束 2025-03-30 01:00:00,
偏移 3600s, 夏令时 0min
如您所见,我们获得了以下信息:
– info.abbrev - 时区缩写名,例如 CET、PT 等 – info.begin, info.end - 给定时区的开始和结束日期(以 sys_seconds 为单位),通常在夏令时转换时会发生变化 – info.offset - 相对于 UTC 时间的偏移量 – info.save - 如果不为零,则表示时区处于夏令时
4 Summary
这真是一趟旅程!我们从简单的当前时间显示开始,逐渐过渡到更复杂的场景,包括 C++20 和 C++23 中提供的各种格式选项, 以及时区。最后,我们探讨了如何检查特定时间点的细节,并检查与其时区相关的信息。