Last Update:
What is the current time around the world? Utilizing std::chrono with time zones in C++23
Table of Contents
In this blog post, we will explore handling dates using std::chrono
, including time zones. We’ll utilize the latest features of the library to retrieve the current time across various time zones, taking into account daylight saving time changes as well. Additionally, we will incorporate new capabilities introduced in C++23, such as enhanced printing functions and more.
Let’s start with the following code that prints the current date and time:
#include <chrono>
#include <print>
int main() {
auto now = std::chrono::system_clock::now();
std::print("now is {}", now);
}
You can run it through Compiler Explorer
In my session, I’m getting the following results:
Now is 2024-11-01 11:44:06.374573703
It’s simple, but what time zone are we in? Can we print it in a shorter form? How can we check the time around the world? What about daylight saving time?
First things first: time output.
Improving the print
As you can see, I used std::print
from C++23, which is available in GCC 14! By default, the time point obtained from ::now()
is printed with full information, but we can change it and adjust it. For example:
Basic Date and Time Formatting
- Show just the date:
{0:%F}
will format the date asYYYY-MM-DD
. - Show time in
hh:mm:ss
format:{0:%T}
will format the time asHH:MM:SS
. - Show the name of the month and/or day of the week:
{0:%A, %B}
will format it asDay, Month
.
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);
}
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
We can print the time, and it’s now clear that it is always in UTC. What about other time zones?
Getting time in my current time zone
C++20 chrono
gives us a powerful module that handles time zones. It’s not that easy, as the library has to reach out to the operating system and get the IANA database (see more @std::chrono::tzdb - cppreference.com.
But as a user, it’s relatively easy for us: we have to use zoned_time
and ask for proper 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);
try
{
for (auto zone: {"Europe/Warsaw",
"America/New_York",
"Asia/Tokyo" } )
{
std::chrono::zoned_time zt{zone, now};
std::print("{0}: {1:%F} {1:%R}\n", zone, zt);
}
}
catch (std::runtime_error& ex)
{
std::print("Error: {}", ex.what());
}
}
See at Compiler Explorer
Example output:
now is 2024-11-12 08:15:22.575519666 UTC and local is: 2024-11-12 08:15:22.575519666
Europe/Warsaw: 2024-11-12 09:15
America/New_York: 2024-11-12 03:15
Asia/Tokyo: 2024-11-12 17:15
Compiler Explorer apparently runs on some servers located in the UTC time zone, so there’s no difference in time. But my time zone - Warsaw/Poland - shows different times, Similar to New York and Tokyo.
Let’s now dive into the details:
- Getting the Current Time:
- We start by obtaining the current time using
std::chrono::system_clock::now()
. This gives us the current time in UTC.
- We start by obtaining the current time using
- Local Time Zone:
- We create a
std::chrono::zoned_time
object usingstd::chrono::current_zone()
, which automatically detects the local time zone of the system where the code is running. This allows us to convert the UTC time to the local time zone.
- We create a
- Time Zone Conversion: - We define three time zones using
std::string_view
: Warsaw, New York, and Tokyo. These are specified using their respective IANA time zone identifiers.- For each time zone, we create a
std::chrono::zoned_time
object, which converts the current UTC time to the specified time zone.
- For each time zone, we create a
- Printing the Results:
- We use
std::print
to display the current time in UTC and the local time zone. - For each specified time zone (Warsaw, New York, Tokyo), we print the date and time using the format specifiers
{0:%F}
for the date (YYYY-MM-DD
) and{0:%R}
for the time (HH:MM
).
- We use
- Error Handling:
- The code is wrapped in a
try-catch
block to handle any potential runtime errors, such as invalid time zone identifiers.
- The code is wrapped in a
Daylight saving time
We can even check some extra information related to our current time zone. We can obtain info
from our zoned_time
and print information like start/end, offset, and more:
#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("now is {} UTC and Warsaw is: {}\n", now, zt_local);
auto info = zt_local.get_info();
std::print("local time info: \nabbrev: {},\n begin {}, end {}, \noffset {}, save {}\n",
info.abbrev, info.begin, info.end, info.offset, info.save);
}
catch (std::runtime_error& ex)
{
std::print("Error: {}", ex.what());
}
}
and daylight info:
#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("time info for {:%F} in {}:\nabbrev: {},\nbegin {}, end {}, \noffset {}, save {}\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("Error: {}", ex.what());
}
}
I’m getting:
time info for 2024-09-14 in Europe/Warsaw:
abbrev: CEST,
begin 2024-03-31 01:00:00, end 2024-10-27 01:00:00,
offset 7200s, save 60min
time info for 2024-11-14 in Europe/Warsaw:
abbrev: CET,
begin 2024-10-27 01:00:00, end 2025-03-30 01:00:00,
offset 3600s, save 0min
As you can see, we get the following information:
info.abbrev
- zone abbreviation name, like CET, PT, etcinfo.begin
,info.end
- start and end date (insys_seconds
) for a given time zone, usually changes when there’s a daylight time zone switchinfo.offset
- offset from UTC timeinfo.save
- if nonzero, indicates that the time zone is on daylight saving time
Summary
What a ride! We began with a simple display of the current time and progressed to more complex scenarios, including various formatting options available in C++20 and C++23, as well as time zones. In the end, we explored how to check details of a specific timepoint and examine the information related to its time zone.
Would you like to see more?
Read my other articles on std::chrono
. See Exploring std::chrono in C++20 - Time Zones or Exploring std::chrono in C++20 - Calendar Types ~2700 words, which are available for C++ Stories Premium/Patreon members.
See all Premium benefits here.
Back to you
- Have you tried std::chrono?
- Do you use the latest additions from C++20 for date support?
Share your comments below.
I've prepared a valuable bonus for you!
Learn all major features of recent C++ Standards on my Reference Cards!
Check it out here:
Similar Articles:
- std::initializer_list in C++ 2/2 - Caveats and Improvements
- Fun with printing tables with std::format and C++20
- std::initializer_list in C++ 1/2 - Internals and Use Cases
- How to Use Monadic Operations for `std::optional` in C++23
- Five Advanced Initialization Techniques in C++: From reserve() to piecewise_construct and More.