Howard Hinnant's date: the chrono extension that became C++20's calendar
A date and time library based on the C++11/14/17 <chrono> header
At a glance
- What is it?
- A header-only C++11/14/17 library for calendar dates, plus tz.h, a full parser of the IANA timezone database. The headers are the easy part; the timezone library is the one that needs a build step and a data source.
- Who is it for?
- Adopt date.h if you are on C++11, C++14 or C++17 and need calendar arithmetic that <chrono> does not provide; adopt tz.h if you need IANA timezone conversion and can accept a compiled source file plus a database source. Do not adopt it if you are already on C++20 and only need std::chrono, or if you cannot supply tzdb data at runtime.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What date.h and tz.h actually solve
The C++ <chrono> header gives you clocks and durations. It does not give you a calendar. There is no year_month_day, no way to ask what weekday a date falls on, no conversion from a civil date to a time_point and back. The README describes date.h as a header-only library that builds on <chrono>, adding new duration and time_point types plus field types such as year_month_day, which it describes as a struct of {year, month, day}. The conversion between field types and time_point types is the core of it.
The second library, tz.h with tz.cpp, is a different animal. The README calls it a complete parser of the IANA timezone database, and notes that the database also carries leap second data, with utilities to compute with it. If your program has to answer "what local time was this UTC instant in this zone", that is the part you want. The first part, date.h, is what you want if your problem is purely calendrical.
The audience is C++ developers who cannot move to C++20 yet, or who need behaviour that predates the standard version. The README states that slightly modified versions of date.h and tz.h were voted into the C++20 working draft at the Jacksonville meeting on 2018-03-17. That is the strongest argument for the library's design: you are not adopting an idiosyncratic API, you are adopting the ancestor of the standard one.
How the headers and the timezone parser fit together
The layout is layered, and the repository makes it visible. include/ holds the headers, src/ holds tz.cpp, test/ holds the test suite. date.h is header-only. iso_week.h, julian.h and islamic.h are also header-only, and each is built on top of date.h: an ISO week calendar, a proleptic Julian calendar, and a proleptic Islamic calendar respectively. The README says the Julian and Islamic calendars are fully interoperable with everything above them, which means they convert through the same field and time_point machinery rather than through their own parallel types.
tz.h sits on top of date.h and is the only component that requires compilation. That single source file is the entire build story for the timezone side. The README points to the tz.html page for installation directions rather than reproducing them.
One design detail worth noticing: the timezone library parses the database rather than hard-coding rules. That is why the topics list includes iana-database, and why the related searches include Use_os_tzdb. The data source is a runtime concern, not a compile-time constant. That has consequences for deployment, which I get to below.
Installing date and running a first conversion
For everything except tz.h, the README's recommended approach is to just include the header. There is no install step for date.h itself. For tz.h you compile src/tz.cpp once.
The README also documents an unsupported vcpkg path. It is explicit that the author does not personally use or maintain the CMake and vcpkg systems, and considers them more trouble than they solve for a project this size, but accepts contributions. The vcpkg commands as given in the README are:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install dateThe README notes that the vcpkg port is updated by Microsoft team members and community contributors, and asks that version lag be reported on the vcpkg repository rather than here.
If you prefer CMake, the README gives this sequence for building and testing with the Makefile generator:
mkdir build
cd build
cmake -DENABLE_DATE_TESTING=ON -DBUILD_TZ_LIB=ON ../
cmake --build . --target testit # Consider '-- -j4' for multithreadingENABLE_DATE_TESTING turns on the test target, BUILD_TZ_LIB turns on the timezone library, and the target is named testit. Expect that target to report failures on most platforms; the README says there are known failures on all platforms except macOS, and even on macOS if C++11 is used. It also says workarounds exist if those failures matter to you. Read that as a statement about the test suite's portability expectations, not as a claim that the library is broken.
The tzdb dependency is the real operational cost
The timezone library is only as good as the database it reads. The README does not spell out, in the section reproduced here, how the database is located at runtime or what happens when it is missing or stale. That is the gap to close before you ship. A binary that links tz.cpp and expects IANA data has an external dependency that a pure date.h user does not have.
The related searches include Use_os_tzdb, which tells you people are asking about the choice between using the operating system's copy of the database and supplying their own. The README as given does not document that switch, so treat the tz.html documentation page as the place to resolve it, not this article.
There is a second operational question the README does not answer: rollback. If a timezone data update changes a historical offset for a zone your application records, there is no documented procedure here for reverting. Programs that store local timestamps computed from tzdb data inherit that exposure.
The test situation compounds this. The README's own framing is that known failures exist on all platforms except macOS, with an additional caveat for C++11 on macOS. For a library whose correctness depends on calendar arithmetic across many calendars and on timezone rules, that is a real adoption consideration, and the README is honest about it rather than hiding it.
When you should reach for something else
If you are compiling as C++20 or later, the standard library already contains the calendar and timezone facilities that date.h and tz.h informed. In that case you are adding a dependency to get something you may already have. The README's standardization note is the evidence for that overlap.
If your need is a single formatted date string, this is more machinery than the problem requires. The library's value is in typed calendar arithmetic and in timezone conversion, not in printf-style formatting.
A concrete alternative on the calendrical side is the C library's own time handling through <ctime>, combined with a formatting routine. The difference in approach is structural: <ctime> gives you a broken-down struct tm and arithmetic over seconds, with no type distinction between a date and an instant, and no calendar types at all. date.h gives you distinct types such as year_month_day and time_point, so the compiler can stop you from adding a duration to a date. That type separation is the whole argument, and it is also the reason the API feels heavier at first.
On the timezone side, the alternative is to shell out to the system's zoneinfo through platform APIs. That keeps the database ownership with the operating system and removes the compiled source file, at the cost of platform-specific code paths and less control over which database version you observe. The README's own framing, that tz.h is a complete parser of the IANA database, describes the trade you are making: you take on the data, and you get the parsing.
Licence and upgrade cost
GitHub reports the licence for this repository as NOASSERTION, which means the automated classifier could not map LICENSE.txt to a known identifier. The README does not discuss licence terms. Read LICENSE.txt directly and have whoever handles licensing at your organisation make the call; nothing here lets me tell you what the terms are.
Upgrade cost splits along the same line as everything else. date.h is a header you copy or include, so upgrading means replacing a header and recompiling. tz.h adds tz.cpp, so an upgrade can change the compiled unit and, if the database format handling changes, the runtime data expectations. The release cadence visible in the repository is uneven: v3.0.5 on 2026-07-28, v3.0.4 on 2025-05-28, v3.0.3 on 2024-10-20. That is roughly a year between minor releases, so budget for pinning a version rather than tracking a stream. The last push to the default branch was on 2026-09-21.
The CMake and vcpkg integrations are the part most likely to drift, and the README says so itself: they are unsupported, and the author does not maintain them. If your build depends on the vcpkg port, your upgrade path runs through contributors to that port, not through this repository.
Editorial conclusion
Adopt date.h if you are on C++11, C++14 or C++17 and need calendar arithmetic that <chrono> does not provide; adopt tz.h if you need IANA timezone conversion and can accept a compiled source file plus a database source. Do not adopt it if you are already on C++20 and only need std::chrono, or if you cannot supply tzdb data at runtime. Before committing, verify that your toolchain matches the test matrix (the README states there are known failures on all platforms except macOS, and even on macOS with C++11), confirm which tzdb source you will use, and check the LICENSE.txt text yourself, because GitHub reports the licence as NOASSERTION.
Frequently asked questions
What datatype is a date in HowardHinnant/date?
The README describes field types such as year_month_day, which it defines as a struct of {year, month, day}. These field types are separate from the time_point types the library also adds, and the library provides conversions between the two.
How can I get the current date in C++ with HowardHinnant/date?
The README does not give a worked example of reading the current date. It describes date.h as building on <chrono> and providing conversions between field types such as year_month_day and time_point types, so the current time comes from <chrono> and the conversion to a calendar date comes from this library. The date.html documentation page is the place to look for the exact call.
How do I represent time and date in C++ with HowardHinnant/date?
The README says the library adds new duration and time_point types to <chrono>, plus field types such as year_month_day, which it describes as a struct of {year, month, day}. Conversions between the field types and the time_point types are provided by the library.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/howardhinnant-date)