Let's say I have the following program to export an object to JSON:
struct MyChronoObject {
std::string name;
std::chrono::system_clock::time_point birthday;
MyChronoObject(const std::string name_) : name(name_) {
birthday = std::chrono::system_clock::now();
}
std::string toJSON1() {
std::string s = "{ \"name\": \"" + name + "\", \"birthday\": ";
s += std::to_string((birthday.time_since_epoch().count() / 1000000));
s += " }";
return s;
}
std::string toJSON2() {
std::string s = "{ \"name\": \"" + name + "\", \"birthday\": ";
s += std::to_string((birthday.time_since_epoch().count()));
s += " }";
return s;
}
void setBirthday(int birthday_in_seconds) {
// how do I properly cast this?
}
};
Which, for toJSON1(), has the output { "name": "Steve", "birthday": 16687719115 }
There are several problems with this code (which I will mention but will probably address them in separate threads), but first and foremost...
The number 16687747280 is not correct. It should be one digit shorter for seconds or 2 digits longer for milliseconds if I go by this: EpochConverter
Not dividing the the birthday by one million, toJSON2(), leads to a number that is one digit too long for microseconds and 2 digits too short for nanoseconds: 16687747280849928.
So which way would be correct (and most efficient) to store and convert the stored epoch time so that I can export it to something that can be used by Javascript?
Thank you in advance!
P.S.: Other questions that I have are:
How do I cast back a number that the C++ program receives from the frontend (like in setBirthday)?
Should I even store the date as chrono object if seconds are sufficient?
How do I add exactly one year so that I land on the same date (e.g. 25.1.2019 to 25.1.2020), considering things like leap years, etc.).
What about dates before 1970?
Note the default unit of std::chrono::system_clock is undefined. Instead of using birthday.time_since_epoch().count() / 1000000, you should cast the time unit to the appropriate unit for you:
std::chrono::duration_cast<std::chrono::seconds>(birthday.time_since_epoch())
.count()
This will give you the amount of second.
You might also use std::chrono::ceil<seconds>, std::chrono::floor<seconds>, std::chrono::round<seconds> for different rounding modes.
To cast from integer back to a time_point, you can do:
std::chrono::sys_time{std::chrono::seconds{birthday_in_second}};
or:
std::chrono::sys_time{std::chrono::milliseconds{birthday_in_millisecond}};
To add/subtract years, you can use:
auto now = std::chrono::system_clock::now();
auto today = std::chrono::year_month_day{std::chrono::floor<std::chrono::days>(now)};
auto today_10_years_ago = today - std::chrono::years{10};
And you can also use using namespace std::chrono::literals to write 10y instead of years{10}. *This is incorrect, see more information in the comment
Note today and today_10_years_ago are year_month_day object now. If you want a time_point with h/m/s information as well, you can do:
auto today_as_time_point = std::chrono::sys_days{today_10_years_ago};
auto time_only = today - now;
auto today_with_time_info = today_as_time_point + time_only;
Yes, the <chrono> library works with time before epoch.
By requirement, all predefined duration types up to chrono::hours are guaranteed to work in the range for at least ±292 years(in practice, many of them will still work in much larger ranges). And types greater than hour, ie. chrono::days, chrono::years are guaranteed for ±40000 years.
So if you know you are going to do something like now - years{1000}, it would be a good idea to convert now to a larger unit first.
I'm still a bit overwhelmed by the casting...
Part of the goal of the <chrono> library is to give high level access to time/date data while avoiding possible errors.
If you want to cast a more precise duration to a less precise duration, ie. from millisecond to second, you are forced to use an explicit cast or through roundings, which will avoid unintended truncation errors.
For more, you might search for Howard Hinnant's talk on the library.
... and extracting something like year out of it
Depends on your need, if your full goal was to serialize a date information, you might want to utilize std::format or {fmt} library to do it automatically:
auto now = std::chrono::system_clock::now();
std::cout << std::format("{:%Y}", now); // This will print only the year
Demo further utilizing formatting libraries. *Note {fmt} library is used as gcc haven't implemented the full std::format library.
duration.count() returns a number of ticks. Not seconds, nor microseconds, nor nanoseconds. Unless the tick period happens to be 1, 10⁻⁶, or 10⁻⁹ seconds.
You have to multiply that by the period, which is given in class attributes of your duration. Which in you case, depends on the clock type (all those are templates, and the period depend on the actual class)
One way is to cast the duration into a duration whose you know the period.
Like
std::chrono::duration_cast<std::chrono::seconds>(birthday.time_since_epoch()).count()
// Instead of birthday.time_since_epoch().count()
Related
I'm trying to update the basic dev library of my project from C++98 to C++11.
In the dev library, there are many functions about time, such as
uint64_t getCurrentMSTime()
{
struct timeval stv;
gettimeofday(&stv, NULL);
uint64_t ms = stv.tv_sec ;
ms = ms * 1000 + stv.tv_usec / 1000;
return ms;
}
I'm trying to change it with std::chrono of C++11.
For now it seems that I have two choices, one is to return time_point, the other is to return immediately std::chrono::milliseconds::rep
std::chrono::time_point<std::chrono::system_clock> getCurrentTime1() {
return std::chrono::system_clock::now();
}
std::chrono::milliseconds::rep getCurrentTime2() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
Well, I know that the first one is more flexible because it returns a time_point, which means that we can convert it into milliseconds, nanoseconds, seconds etc, whereas the second one is return only milliseconds.
But let's say that the developers use ONLY milliseconds so we can ignore the flexible issue.
In this case, which one is better?
BTW, the developers would do something like this: std::map<std::string, ???> mp;. So my code will decide the ??? part.
std::map<std::string, std::chrono::time_point<std::chrono::system_clock>> mp{std::string("abc"), getCurrentTime1()};
vs
std::map<std::string, std::milliseconds::rep> mp{std::string("abc"), getCurrentTime2()};.
Which one is better? Or are they almost the same?
I agree with the currently accepted answer that you should value type-safety, and not return an integral type. However I disagree that returning milliseconds is best.
Type safety applies to the difference between time points and time durations as well. For example it makes perfect sense to add two time durations. But it is nonsensical to add two time points, though you can subtract them yielding a time duration.
Since the meaning of getCurrentTime() is to return the current point in time, one should return a std::chrono::time_point. One can easily choose to return a time_point based on system_clock with milliseconds precision:
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
getCurrentTime()
{
return std::chrono::time_point_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now());
}
In C++20, there's a convenience type alias for this type to make it a little easier to spell. You could create such a type alias for yourself if you would like to get a head start on things:
std::chrono::sys_time<std::chrono::milliseconds>
getCurrentTime()
{
return std::chrono::time_point_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now());
}
Or you can create an even shorter name for use within your application, perhaps:
using MSTime = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
...
MSTime
getCurrentMSTime()
{
return std::chrono::time_point_cast<MSTime::duration>(
std::chrono::system_clock::now());
}
You certainly don't want to throw away the type information that <chrono> offers. If you convert the time_point you get from the system clock into an integral value right away, you can equally well keep the legacy function as it is.
Instead, decide upfront whether you want to handle points in time relative to the epoch or not. The old function suggests that you want this, so your function should look like this;
std::chrono::milliseconds getDurationSinceEpoch()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
}
But let's say that the developers use ONLY milliseconds so we can ignore the flexible issue
Don't. What you get is here is for free. Whenever this requirement changes, and some developer mixes getDurationSinceEpoch() return values with durations in whatever resolution, it becomes quite brittle. By baking the correct units into your functions, you guard against future bugs.
Last, you want your map to have this signature:
std::map<std::string, std::chrono::milliseconds>
I want to time-tag a stream of data I produce, for which I want to use std::chrono::steady_clock.
These time-stamps are stored with the data ( as array of uint64 values?), and I will later need to process these time-stamps again.
Now, I haven't been using the std::chrono library at all so far, so I do need a bit of help on the syntax and best practices with this library.
I can get & store values using:
uint64_t timestamp = std::chrono::steady_clock::now().time_since_epoch().count();
but how do I best:
On reading the data create a timepoint from the uint64 ?
Get the ticks-per-second (uint64) value for the steady_clock?
Find a "cut-off" timepoint (as uint64) that lies a certain time (in seconds) prior a given timepoint?
Code snippets for the above would be appreciated.
I want to combine the three above essentially to do the following: Having an array of (increasing) time-stamp values (as uint64), I want to truncate it such that all data 'older' than last-time-stamp minus X seconds is thrown away.
Let's have a look at the features you might use in the cppreference documentation for chrono.
First off, you need to decide which clock you want to use. There is the steady_clock which you suggested, the high_resolution_clock and the system_clock.
high_resolution_clock is implementation dependent, so let's put this away unless we really need it. The steady_clock is guaranteed to be monotonic, but there is no guarantee of the meaning for the value you are getting. It's ideal for sorting events or measuring their intervals, but you can't get a timepoint out of it.
On the other hand, system_clock has a meaning, it's the UNIX epoch, so you can get a time value out of it, but is not guaranteed to be monotonic.
To get the period (duration of one tick) of a steady_clock, you have the period member:
auto period = std::chrono::steady_clock::period();
std::cout << "Clock period " << period.num << " / " << period.den << " seconds" << std::endl;
std::cout << "Clock period " << static_cast<double>(period.num) / period.den << " seconds" << std::endl;
Assuming you want to filter events that happened in the last few seconds using steady_clock values, you first need to compute the number of ticks in the time period you want and subtract it from now. Something along the lines of:
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t t_c = std::chrono::system_clock::to_time_t(now - std::chrono::seconds(10));
And use t_c as cutoff point.
However, do not rely on std::chrono::steady_clock::now().time_since_epoch().count(); to get something meaningful - is just a number. The epoch for the steady_clock is usually the boot time. If you need a time, you should use system_clock (keeping in mind that is not monotonous).
C++20a introduces some more clocks, which are convertible to time.
As it took me far too long to figure it out from various sources today, I'm going to post my solution here as self-answer. ( I would appreciate comments on it, in case something is not correct or could be done better.)
Getting a clock's period in seconds and ticks-per-second value
using namespace std::chrono;
auto period = system_clock::period();
double period_s = (double) period.num / period.den;
uint64 tps = period.den / period.num;
Getting a clock's timepoint (now) as uint64 value for time-stamping a data stream
using namespace std::chrono;
system_clock::time_point tp_now = system_clock::now();
uint64 nowAsTicks = tp_now.time_since_epoch().count();
Getting a clock's timepoint given a stored uint64 value
using namespace std::chrono;
uint64 givenTicks = 12345; // Whatever the value was
system_clock::time_point tp_recreated = system_clock::time_point{} + system_clock::duration(givenTicks);
uint64 recreatedTicks = tp_now.time_since_epoch().count();
Assert( givenTicks == recreatedTicks ); // has to be true now
The last ( uint64 to timepoint ) was troubling me the most. The key-insights needed were:
(On Win10) The system_clock uses a time-resolution of 100 nanoseconds. Therefore one can not directly add std::chrono::nanoseconds to its native time points. (std::chrono:system_clock_time_point)
However, because the ticks are 100's of nanoseconds, one can also not use the next higher duration unit (microseconds) as it cannot be represent as an integer value.
One could use use an explicit cast to microseconds, but that would loose the 0.1us resolution of the the tick.
The proper way is to use the system_clock's own duration and directly initialize it with the stored tick value.
In my search I found the following resources most helpful:
Lecture of Howard Hinnant on YouTube - extremely helpful. I wish I would have started here.
cppreference.com on time_point and duration and time_since_epoch
cplusplus.com on steady clock and time_point
A nice place to look as usual is the reference manual :
https://en.cppreference.com/w/cpp/chrono
In this case you are looking for :
https://en.cppreference.com/w/cpp/chrono/clock_time_conversion
Since really you are using a clock with "epoch" 1/1/70 as origin and ms as unit.
Then just use arithmetic on durations to do the cutoff things you want :
https://en.cppreference.com/w/cpp/chrono/duration
There are code examples at bottom of each linked page.
I have already found several answers related to converting a std::time_t value to System::DateTime and back. However, almost all answers seem to neglect that the type of std::time_t is actually undefined in the standard. Most solutions just cast std::time_t to whatever needed or apply arithmetic operations to a std::time_t object which is possible since it's an arithmetic type, but there is no specification about the result of such an operation. I know that most compilers define time_t as an int of some size but the fact alone that it has changed from int32 to int64 in many implementations recently shows that changes are indeed possible.
So I've come up with this solution which should work with any type of std::time_t. It works from what I have seen. But I was wondering - Are there any possible pitfalls I might be unaware of?
template <>
inline System::DateTime marshal_as(const std::time_t &from_object)
{
// Returns DateTime in Local time format from time_t (assumed to be UTC)
const auto unix_epoch = makeUtcTime(1970, 1, 1, 0, 0, 0);
const auto unix_epoch_dt = System::DateTime(1970, 1, 1, 0, 0, 0, System::DateTimeKind::Utc);
const auto secondsSinceEpoch = std::difftime(from_object, unix_epoch);
return const_cast<System::DateTime&>(unix_epoch_dt).AddSeconds(secondsSinceEpoch).ToLocalTime();
} // end of System::DateTime marshal_as(const std::time_t &from_object)
template <>
inline std::time_t marshal_as(const System::DateTime &from_object)
{
// Returns time_t in UTC format from DateTime
auto from_dt = const_cast<System::DateTime&>(from_object).ToUniversalTime();
return makeUtcTime(from_dt.Year, from_dt.Month, from_dt.Day, from_dt.Hour, from_dt.Minute, from_dt.Second);
} // end of std::time_t marshal_as(const System::DateTime &from_object)
3 assumptions were made:
Resulting std::time_t should be in UTC since it doesn't contain any info on localization
Resulting System::DateTime should be local time since System::DateTime::Now returns a localized DateTime
makeUtcTime is a helper function creating a std::tm from the values supplied and creates a UTC std::time_t out of it. This is currently implemented using _mkgmtime because our interop code can safely rely on the existence of Microsoft extensions. However, a UTC version of mktime is readily available in other compilers as well (standard mktime expects local time).
2 less important things to consider:
The const_cast is necessary because the marshal_as-template expects a const T& as parameter and I can't access the properties of a const .NET value-type object. However there might be a better solution.
Should the unix_epoch... stuff be static const?
(I wasn't sure if this should be posted on "Programmers Exchange" since it's more of a discussion but since it's a very specific C++ question I thought SO might be the better place to ask)
It just isn't very productive to insist on a "standard conformant" way to make this conversion. The only place where an std::time_t and a System::DateTime are ever going to meet is covered by the Ecma-372 standard. Of which there is right now, and surely will ever be, only one implementation. The Mono project could be assumed to be the most likely source of another one, but right now they appear entirely uninterested in providing a mixed-mode implementation, the only reason you'd ever consider using C++/CLI.
std::time_t is steadily marching towards the Y2K38 disaster. With Microsoft pre-emptively having done something about it, and really having to do so because they went for LLP64, but everybody else counting on their LP64 data model keeping them out of trouble. In other words, no remaining 32-bit processors still running in 2038. This could well be a self-fulfilling prophesy.
Regardless, the conversion is going to have to work with elapsed seconds since 1/1/1970. And that can be a 32-bit or a 64-bit integral value, depending on implementation. The only warranty I can give is that this code is at least good until 2038:
#include <ctime>
using namespace System;
public ref class Conversions {
public:
static DateTime time_t2DateTime(std::time_t date) {
double sec = static_cast<double>(date);
return DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind::Utc).AddSeconds(sec);
}
static std::time_t DateTime2time_t(DateTime date) {
TimeSpan diff = date.ToUniversalTime() - DateTime(1970, 1, 1);
return static_cast<std::time_t>(diff.TotalSeconds);
}
};
Here's the solution my team arrived at:
DateTime represents the number of mixed-fractional days since midnight December 30, 1899, expressed as a double. I believe that this epoch date was used to account for the fact that 1900 was not a leap year, and it allows for an extra two days (Why two and not one? - It is not clear to me why Dec 31, 1899 was not chosen as their epoch.)
So a DateTime of 2.50 would be equivalent to January 1, 1900 12:00:00 , (i.e. the fraction represents 1/2 the day - 12PM).
We calculated that Jan 1, 1970 - the Unix Epoch - is 25569 days after the DateTime Epoch.
So the equivalent formula would be:
#include <time.h>
System::DateTime toDateTime(time_t &t)
{
return 25569.0 + t / 86400.0; // ensure you use floating point math or you will truncate the fractional portion
}
What is the correct way to persist std::chrono time_point instances and then read them back into another instance of the same type?
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
time_point_t tp = std::chrono::high_resolution_clock::now();
serializer.write(tp);
.
.
.
time_point_t another_tp;
serializer.read(another_tp);
The calls to write/read, assume that the instance of type time_point_t, can be somehow converted to a byte representation, which can then be written to or read from a disk or a socket etc.
A possible solution suggested by Alf is as follows:
std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
//Generate POD to write to disk
unsigned long long ns0 = t0.time_since_epoch().count();
//Read POD from disk and attempt to instantiate time_point
std::chrono::high_resolution_clock::duration d(ns0)
std::chrono::high_resolution_clock::time_point t1(d);
unsigned long long ns1 = t1.time_since_epoch().count();
if ((t0 != t1) || (ns0 != ns1))
{
std::cout << "Error time points don't match!\n";
}
Note: The above code has a bug as the final instantiated time point does not match the original.
In the case of of the old style time_t, one typically just writes the entire entity to disk based on its sizeof and then reads it back the same way - In short what would be the equivalent for the new std::chrono types?
Reading from a disk or socket implies that you might be reading in an instance of the application that did not do the write. And in this case, serializing the duration alone is not sufficient.
A time_point is a duration amount of time since an unspecified epoch. The epoch could be anything. On my computer the epoch of std::chrono::high_resolution_clock is whenever the computer booted. I.e. this clock reports the number of nanoseconds since boot.
If one application writes the time_since_epoch().count(), the computer is rebooted, and then another (or even the same) application reads it back in, the read in value has no meaning whatsoever, unless you happen to somehow know the amount of time between boots.
To reliably serialize a time_point one has to arrange for the writer and the reader to agree upon some epoch, and then ensure that the time_point written and read is with respect to that epoch. For example one might arrange to use the POSIX epoch: New Years 1970 UTC.
As it turns out, every std::chrono::system_clock implementation I'm aware of uses Unix time, a close approximation of UTC measured from New Years 1970. However I know of no common epoch for std::chrono::high_resolution_clock.
Only if you can somehow ensure that the reader and writer clocks agree upon a common epoch, can you serialize a time_point as a duration.
the time_point constructor takes a duration, and you can get a duration from member time_since_epoch. thus the question reduces to serialize a duration value. and duration has a constructor that takes a number of ticks, and a member function count that produces the number of ticks.
all this just by googling std::chrono::time_point and looking at the cppreference documentation google landed me on.
it's often a good idea to read the documentation.
Addendum: an example.
#include <chrono>
#include <iostream>
#include <typeinfo>
using namespace std;
auto main() -> int
{
using Clock = chrono::high_resolution_clock;
using Time_point = Clock::time_point;
using Duration = Clock::duration;
Time_point const t0 = Clock::now();
//Generate POD to write to disk
Duration::rep const ns0 = t0.time_since_epoch().count();
//Read POD from disk and attempt to instantiate time_point
Duration const d(ns0);
Time_point const t1(d);
cout << "Basic number type is " << typeid( ns0 ).name() << "." << endl;
if( t0 != t1 )
{
cout << "Error time points don't match!" << endl;
}
else
{
cout << "Reconstituted time is OK." << endl;
}
}
With Visual C++ 12.0 the reported basic type is __int64, i.e. long long, while with g++ 4.8.2 in Windows the reported type is x, which presumably means the same.
With both compilers the reconstituted time is identical to the original.
Addendum: As noted by Dina in the comments, as of C++14 the C++ standard doesn't specify the epoch, and so to make this work across machines or with different clocks it's necessary to add additional steps that normalize the epoch for the serialized data, e.g. and most naturally to Posix time, i.e. time since since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970.
I have a program that uses time() and localtime() to set an internal clock, but this needs to be changed so that the internal clock is independent of the user and the "real" time. I need to be able to set any reasonable starting time, and have it count forward depending on a timer internal to the program. Any ideas on the best way to approach this? Here's the excerpt:
#define ConvertToBCD(x) ((x / 10) << 4) | (x % 10);
time_t tm;
time(&tm);
struct tm *tm_local= localtime(&tm);
tm_local->tm_year %= 100;
tm_local->tm_mon++;
timedata[0] = ConvertToBCD(tm_local->tm_year);
timedata[1] = ConvertToBCD(tm_local->tm_mon);
timedata[2] = ConvertToBCD(tm_local->tm_mday);
timedata[3] = (tm_local->tm_wday + 6) & 7;
if (!(TimeStatus & 0x02)) tm_local->tm_hour %= 12;
timedata[4] = ((tm_local->tm_hour < 12) ? 0x00 : 0x40) | ConvertToBCD(tm_local->tm_hour);
timedata[5] = ConvertToBCD(tm_local->tm_min);
timedata[6] = ConvertToBCD(tm_local->tm_sec);
A time_t, under POSIX complient systems, is just the number of seconds since the epoch, 1 Jan 1970 0:00:00.
Just add a (possibly negative) value to a time_t to change the time, ensuring that the value doesn't overflow, then use localtime as usual.
If you only need whole second resolution, then time() can be used; if you need sub-second resolution, use gettimeofday().
However, if you want to be able to control the values returned, then you will need to define yourself a surrogate for time() (or gettimeofday()). Most libraries are designed along the lines described in Plauger's The Standard C Library, and you can often provide a function called time() that behaves as you want, replacing the standard version. Alternatively, and more safely, you can revise your code to call a function of your own devising, perhaps called simulated_time(), where for production work you can have simulated_time() call the real time() (possibly via an inline function in both C99 and C++) but it can be your own version that schedules time to change as you need.
You don't need to alter your use of localtime(); it simply converts whatever time_t value you give it into a struct tm; you want it to give answers just as it always did.
The way I understand it is that you want an internal clock which gets updated according to the progress the real clock makes.
So then you would create something like this:
struct myTime
{
time_t userStart;
time_t systemStart;
time_t curTime;
};
void initTtime(struct myTime *t, time_t time)
{
t->userStart=time;
t->systemStart=time(NULL);
}
time_t getTime(struct myTime *t)
{
t->curTime = t->userStart + time(NULL)-t->systemStart;
return t->curTime;
}
so using initTime you set the current time you want to have, this gets linked to the system time at that moment in time. When you call getTime using that struct, it updates the starting point with the amount of time progressed. (Note, i haven't tested the code and you can either use the struct directly if you want).
For subsecond precision replace time() and time_t by the gettimeofday equivalent. And for conversion, ascii arting, breakdown to anything else than a second counter you can still use the unix function.