I would like to print or extract year/month/day values.
I don't want to use time_t
because of the year 2038 problem, but all examples I found on the Internet use it to convert time_point
to tm
.
Is there a simple way to convert from time_point to tm (preferably without boost)?
An implementation like timesub from libc would be my last resort: http://www.opensource.apple.com/source/Libc/Libc-262/stdtime/localtime.c
Edit: After reading the suggested links and doing some more research, I came to the following conclusion.
- Using time_t where it is 64bit long is ok (for most purposes).
- Using Boost.Date_Time for portable code.
It is noteworthy that Boost.Date_Time can be a header-only library. Source: http://www.boost.org/doc/libs/1_53_0/more/getting_started/unix-variants.html#header-only-libraries
Answer updated with better algorithms, link to detailed description of the algorithms, and complete conversion to
std::tm
.The first thing to note is that
std::chrono::time_point
is templated not only onduration
, but also on the clock. The clock implies an epoch. And different clocks can have different epochs.For example, on my system,
std::chrono::high_resolution_clock
andstd::chrono::steady_clock
have an epoch of: whenever the computer booted up. If you don't know what time the computer booted up, there is no way to convert thattime_point
to any calendar system.That being said, you were probably talking just about
std::chrono::system_clock::time_point
, as thistime_point
, and only thistime_point
, is required to have a deterministic relationship with the civil (gregorian) calendar.As it turns out, every implementation of
std::chrono::system_clock
I'm aware of is using unix time. This has an epoch of New Years 1970 neglecting leap seconds.This isn't guaranteed by the standard. However you can take advantage of this fact if you want to with the following formulas found at:
First off, warning, I'm using the latest C++1y draft, which includes great new
constexpr
tools. If you need to back off some of theconstexpr
attributes for your compiler, just do so.Given the algorithms found at the above link, you can can convert a
std::chrono::time_point<std::chrono::system_clock, Duration>
to astd::tm
, without usingtime_t
with the following function:Also note that the
std::chrono::system_clock::time_point
on all existing implementations is a duration in the UTC (neglecting leap seconds) time zone. If you want to convert thetime_point
using another timezone, you will need to add/subtract the duration offset of the timezone to thestd::chrono::system_clock::time_point
prior to converting it to a precision ofdays
. And if you further want to take leap seconds into account, then adjust by the appropriate number of seconds prior to truncation todays
using this table, and the knowledge that unix time is aligned with UTC now.This function can be verified with:
Which for me currently prints out:
In case chrono-Compatible Low-Level Date Algorithms goes offline, or gets moved, here are the algorithms used in
make_utc_tm
. There are in-depth explanations of these algorithms at the above link. They are well-tested, and have an extraordinarily large range of validity.Update
More recently I have wrapped the above algorithms up into a freely available date/time library documented and available here. This library makes it very easy to extract a year/month/day from
std::system_clock::time_point
, and even hours:minutes:seconds:fractional-seconds. And all without going throughtime_t
.Here is a simple program using the above header-only library to print out the current date and time in the UTC timezone, to the precision of whatever
system_clock::time_point
offers (in this case microseconds):Which just output for me:
This library effectively turns
std::chrono::system_clock::time_point
into an easy-to-use date-time type.There's nothing to support calendar dates in the Standard Library apart from the C library functions based on
time_t
.Options are, in order of my preference:
gmtime()
I have used Howard Hinnant's date library to write a function that converts from
time_point
tostruct tm
:This effectively bypasses
time_t
with its lurking Y2038 problem on 32-bit systems. This function has been contributed to this GitHub wiki, where I hope others will contribute other useful examples and recipes.