# How to Format std::chrono Types with fmtlib: A Complete Guide to Date and Time Output in C++

> Format std::chrono types with fmtlib using strftime-style specifiers. Learn to output C++ date and time with ease using fmt/chrono.h.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: tutorial
- Published: 2026-09-04

---

**Include `<fmt/chrono.h>` and use strftime-style specifiers like `{:%Y-%m-%d}` to format `std::chrono::system_clock::now()` and other chrono types with fmtlib.**

The {fmt} library provides first-class support for C++ chrono types through specialized formatters defined in the `fmtlib/fmt` repository. To format chrono types like `std::chrono::system_clock::now()`, you include the `<fmt/chrono.h>` header, which exposes formatters for `std::chrono::duration`, `std::chrono::time_point`, and `std::tm` structures. This integration enables type-safe, high-performance date and time formatting using familiar strftime syntax directly within fmtlib's format strings.

## Enabling Chrono Support

Before formatting any chrono types, you must include the `<fmt/chrono.h>` header. This header, located at [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h) in the source tree, provides the necessary template specializations that teach fmtlib how to convert temporal types into strings. Without this header, attempts to format chrono objects will result in compilation errors because the primary `formatter` template lacks the required specializations.

## Formatting std::chrono::time_point

The formatter for `std::chrono::time_point` implementations works by converting the time point to a broken-down calendar representation. In [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h) (lines 68-78), the library defines a `formatter<sys_time<Duration>, Char>` specialization that handles any `time_point` whose clock provides a `time_since_epoch()` conversion to `std::chrono::duration`.

When you pass `std::chrono::system_clock::now()` to `fmt::print`, the library performs three internal steps:

1. Instantiates the `formatter<sys_time<Duration>, Char>` for the specific `system_clock::time_point` type.
2. Calls `gmtime` to convert the duration since epoch into a `std::tm` structure (lines 70-86).
3. Delegates to the `formatter<std::tm, Char>` specialization to parse the strftime-style format string.


```cpp
#include <fmt/chrono.h>
#include <chrono>

int main() {
    auto now = std::chrono::system_clock::now();
    fmt::print("Full timestamp: {}\n", now);           // Default ISO-like output
    fmt::print("Date only:      {:%Y-%m-%d}\n", now);  // 2024-09-04
    fmt::print("Time only:      {:%H:%M:%S}\n", now);  // 14:23:07
}

```

### Handling Sub-Second Precision

For time points with sub-second precision, the implementation extracts the remainder of the duration after converting to seconds (lines 86-99 in [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h)). This remainder passes to the `do_format` helper, which appends fractional seconds when you use the `%f` specifier.


```cpp
#include <fmt/chrono.h>
#include <chrono>

int main() {
    using namespace std::chrono_literals;
    auto precise = std::chrono::system_clock::now() + 1234ms;
    fmt::print("Precise: {:%Y-%m-%d %H:%M:%S.%f}\n", precise);
    // %f prints fractional seconds (microseconds)
}

```

## Formatting std::chrono::duration

Durations format automatically without requiring explicit specifiers, though you can combine them with time points in the same format string. The library handles safe duration casting internally to prevent precision loss.


```cpp
#include <fmt/chrono.h>
#include <chrono>

int main() {
    using namespace std::chrono_literals;
    fmt::print("Elapsed: {} {}\n", 42s, 150ms);  // Output: Elapsed: 42s 150ms
}

```

## Format Specifier Reference

According to [`doc/syntax.md`](https://github.com/fmtlib/fmt/blob/main/doc/syntax.md) in the fmtlib repository, chrono format specifications follow standard strftime conventions. Place specifiers after the `%` character inside the format braces:

- **%Y**: Four-digit year (e.g., 2024).
- **%m**: Zero-padded month (01-12).
- **%d**: Zero-padded day of month (01-31).
- **%H**: Hour in 24-hour format (00-23).
- **%M**: Minute (00-59).
- **%S**: Second (00-59).
- **%f**: Fractional seconds (microseconds).

The [`doc/api.md`](https://github.com/fmtlib/fmt/blob/main/doc/api.md) file (section *Date and Time Formatting*) documents additional usage patterns and examples for these specifiers.

## Implementation Details

The chrono formatting system relies on several template specializations in [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h):

- `formatter<sys_time<Duration>, Char>`: Handles system clock time points (lines 68-78).
- `formatter<utc_time<Duration>, Char>`: Supports UTC-specific formatting.
- `formatter<local_time<Duration>, Char>`: Formats local time representations.

All specializations convert time points to `std::tm` using `gmtime` for consistent UTC output, then delegate to the generic `std::tm` formatter. This architecture ensures that any `std::chrono::time_point` compatible with `time_since_epoch()` works correctly, including `steady_clock` and `high_resolution_clock` time points (though the calendar date for non-system clocks represents time since their respective epochs).


```cpp
#include <fmt/chrono.h>
#include <chrono>

int main() {
    auto steady = std::chrono::steady_clock::now();
    fmt::print("Steady clock (seconds): {:%S}\n", steady);
}

```

## Summary

- **Include `<fmt/chrono.h>`** to enable formatting for all `std::chrono::duration` and `std::chrono::time_point` types.
- **Use strftime-style specifiers** (e.g., `%Y`, `%m`, `%d`, `%H`, `%M`, `%S`, `%f`) inside format strings like `{:%Y-%m-%d}`.
- **Access sub-second precision** using the `%f` specifier, which relies on the internal `do_format` helper to extract fractional components from lines 86-99 of [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h).
- **Format any compatible clock** because the `formatter<sys_time<Duration>, Char>` template works with any time point convertible to duration since epoch.
- **Reference [`doc/syntax.md`](https://github.com/fmtlib/fmt/blob/main/doc/syntax.md)** for the complete list of chrono format specifications and [`doc/api.md`](https://github.com/fmtlib/fmt/blob/main/doc/api.md) for official usage examples.

## Frequently Asked Questions

### Which header do I need to include to format chrono types with fmtlib?

You must include `<fmt/chrono.h>` in addition to the standard fmt headers. This header defines the required `formatter` specializations in [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h) (lines 68-78) that handle `std::chrono::time_point`, `std::chrono::duration`, and `std::tm` objects. Without this header, the compiler cannot resolve formatting for chrono types.

### Can I format time points from clocks other than `system_clock`?

Yes. The `formatter<sys_time<Duration>, Char>` specialization works with any `std::chrono::time_point` whose clock provides a `time_since_epoch()` conversion to `std::chrono::duration`. This includes `steady_clock` and `high_resolution_clock`, though the calendar dates produced represent time elapsed since those clocks' specific epochs rather than actual calendar dates.

### How do I display fractional seconds when formatting `system_clock::now()`?

Use the `%f` format specifier in your format string, such as `{:%Y-%m-%d %H:%M:%S.%f}`. Internally, the library extracts the sub-second remainder from the duration (lines 86-99 in [`include/fmt/chrono.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/chrono.h)) and passes it to the `do_format` helper, which outputs the fractional component as microseconds.

### What format syntax does fmtlib use for chrono types?

fmtlib uses standard **strftime-style syntax** where format specifiers begin with `%`. Supported specifiers include `%Y` (year), `%m` (month), `%d` (day), `%H` (hour), `%M` (minute), `%S` (second), and `%f` (fractional seconds), as documented in [`doc/syntax.md`](https://github.com/fmtlib/fmt/blob/main/doc/syntax.md). Everything inside the `{:%...}` braces is interpreted as a chrono format specifier and processed by the specialized formatter templates.