I wrote the below code to get the number of seconds since midnight.
However, I'm not great with the C time date structs. Is there a simpler way of doing this using a standard C++ library?
// Get today's date
time_t aTime = time(NULL);
// Set the time to midnight
struct tm* tm = localtime(&aTime);
tm->tm_sec = 0;
tm->tm_min = 0;
tm->tm_hour = 0;
tm->tm_isdst = -1;
time_t midnight = mktime(tm);
// Create object representing now
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
// Number of seconds (now) since Epoch
const uint64_t nowSecsSinceEpoch = now.tv_sec;
// Number of seconds (now) since midnight = seconds (now) since Epoch minus seconds (at midnight) since Epoch
const uint64_t nowSecsSinceMidnight = nowSecsSinceEpoch - midnight;
It depends on if you mean time since midnight UTC, or time since midnight local time, or perhaps in some non-local, far away time zone.
This is also made much easier in C++20. But there exists a preview of the C++20 parts of the <chrono> library that can be used with C++11-17.
Time since midnight UTC
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
auto now = system_clock::now();
auto today = floor<days>(now);
auto tod = duration_cast<seconds>(now - today);
}
This simply gets the current time (UTC), truncates it to a days-precision time_point, and then subtracts the two and truncates that difference to seconds precision.
Time since local midnight
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
auto now = current_zone()->to_local(system_clock::now());
auto today = floor<days>(now);
auto tod = duration_cast<seconds>(now - today);
}
This version finds your computer's currently set local time zone, and then gets the current local time via the time_zone's to_local() member function. And then proceeds as before.
Time since some other midnight
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
auto now = locate_zone("Australia/Sydney")->to_local(system_clock::now());
auto today = floor<days>(now);
auto tod = duration_cast<seconds>(now - today);
}
Finally, this version finds the time_zone associated with Sydney Australia, and then uses that time zone and proceeds as before.
The C++20 preview <chrono> library is free and open-source. It puts everything in namespace date, and in two headers (and one source):
date.h: A header-only library that will do the UTC part, but has no time zone support.
tz.h: For the time zone support. This requires some installation.
Related
case
I need to write a program that moves files around at times that are set in a configuration file. The time can be 00:00:01 seconds untill 24:00:00 hours. This is converted into seconds. So if somebody wants to move a file at 12:00:00 pm today, the move time is 12 * 60 * 60 = 43200 seconds. This is done every day and the program needs to check if that time is reached.
I use the chrono library to get the time now since epoch in seconds using:
auto dayInSeconds = 86400;
auto currentTime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock().now().time_since_epoch());
auto timeWithoutDays = currentTime % dayInSeconds;
std::cout << "time in seconds today: " << timeWithoutDays.count() << std::endl;
problem
This shows me the current time since epoch in seconds. But now for example ( 13:45 Amsterdam time) it returns a number of: 42294. If I run it exactly five seconds later in a loop it returns 42299. So the counting seems to be correct. What is not correct, is that 42299 seconds is 1174 hours (42299/ 60 /60). Which should mean that is now 11:somewhat AM but its 13:32 PM. Or not? What am I doing wrong? I just need to know, how many seconds have passed since 00:00:00 this day. So i can check if the user set time is passed and stuff needs to be done.
I would like to keep using the chrono library for all sorts of reasons, but mainly because I understand that one. So if answers use that library, it would be a great help. I have a feeling i'm doing something completely stupid.
fix
For any other that seeks the same answer. I fixed it like this, it seems to work:
auto dayInSeconds = 86400;
auto amsterdamUTCPlusTime = 7200;
auto currentTime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock().now().time_since_epoch());
auto timeWithoutDays = currentTime % dayInSeconds;
auto currentTimeInSeconds = timeWithoutDays.count() + amsterdamUTCPlusTime;
std::cout << "time in seconds today: " << currentTimeInSeconds << std::endl;
C++20 brings extensions to <chrono> to deal with timezones. It isn't shipping yet (to the best of my knowledge). But here is what it will look like:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
zoned_time zt{"Europe/Amsterdam", floor<seconds>(system_clock::now())};
auto lt = zt.get_local_time();
auto tod = lt - floor<days>(lt);
cout << "time in seconds today: " << tod.count() << '\n';
cout << hh_mm_ss{tod} << '\n';
}
Example output:
time in seconds today: 71923
19:58:43
If your computer's local time zone setting is already set to "Europe/Amsterdam", then "Europe/Amsterdam" above can be replaced with current_zone().
This gets the current time in UTC, truncates it to seconds precision, and then pairs it with the "Europe/Amsterdam" time_zone to create a zoned_time. Then the local time is extracted from the zoned_time. The local time of day is simply the local time minus the beginning of that day (floor<days>(lt)). This is stored in tod which has type seconds. Wrapping it in a hh_mm_ss prints it out in a hh:mm:ss format.
There exists a free, open-source C++20 <chrono> preview library which can be used with C++11/14/17 to do this. To use it, it must be installed. There's a single source file to be compiled, tz.cpp, and it needs to have access to the IANA time zone database, which can be automatically downloaded with specific build settings.
The source code above must be trivially modified by adding #include "date/tz.h" and using namespace date;. In C++11 and 14, change zoned_time to zoned_seconds, and hh_mm_ss to hh_mm_ss<seconds>.
Another possibility is to build your own UTC offset calculator for just Amsterdam (assuming current rules). The advantage of this is that it can use of subset of the free, open-source C++20 <chrono> preview library which is header-only, and thus requires no installation, and does not need the IANA time zone database. That could like this:
#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
auto AmsterdamOffset = [](system_clock::time_point tp)
{
auto const y = year_month_day{floor<days>(tp)}.year();
auto const start = sys_days{Sunday[last]/March/y} + 1h;
auto const end = sys_days{Sunday[last]/October/y} + 1h;
if (start <= tp && tp < end)
return 2h;
return 1h;
};
auto now = floor<seconds>(system_clock::now());
auto local_now = now + AmsterdamOffset(now);
auto tod = local_now - floor<days>(local_now);
cout << "time in seconds today: " << tod.count() << '\n';
cout << hh_mm_ss{tod} << '\n';
}
This program hardcodes the fact that Amsterdam daylight saving begins on the last Sunday of March at 01:00:00 UTC and ends on the last Sunday of October at 01:00:00 UTC.
After that, the program logic is much like the C++20 solution shown above. In C++11, 1h and 2h will have to be changed to hours{1} and hours{2} respectively.
And yet another approach: Posix time zones
There is also a Posix time zone library at this link in ptz.h. This is also a header-only library, so no install issues. It allows you to use the C++20 zoned_time combined with Posix time zones. This will give you the same results as the example above with the "hard coded" rules for Amsterdam (which are valid back through 1978).
#include "date/ptz.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
// Amsterdam rules
Posix::time_zone tz{"CET-1CEST,M3.5.0,M10.5.0/3"};
zoned_time zt{tz, floor<seconds>(system_clock::now())};
auto lt = zt.get_local_time();
auto tod = lt - floor<days>(lt);
cout << "time in seconds today: " << tod.count() << '\n';
cout << hh_mm_ss{tod} << '\n';
}
The above assumes C++17. If in C++11 or 14 the syntax becomes a little messier:
zoned_time<seconds, Posix::time_zone> zt{tz, floor<seconds>(system_clock::now())};
The Posix::time_zone is not part of the C++20 <chrono> library, but is compatible with it. It can be used with the C++20 std::chrono::zoned_time class template as shown above.
You can use localtime function and get the current time from system.
int getIntTime()
{
struct timeb now;
struct tm *curtime;
curtime = localtime(&now);
return(curtime->tm_hour * 10000L + curtime->tm_min * 100L + curtime->tm_sec);
}
And also you should convert the set time in confgi file to same as output of this function and compare them as follow:
if(getIntTime() >= converted_time_configfile )
{
//do processing
}
I have a problem with Visual Studio 2017.
I'm trying to get the current time and date with millisecond resolution. I tried the follwing code in a few compilers:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <ctime>
#include <chrono>
using namespace std;
using namespace chrono;
int main()
{
high_resolution_clock::time_point p = high_resolution_clock::now();
milliseconds ms = duration_cast<milliseconds>(p.time_since_epoch());
seconds s = duration_cast<seconds>(ms);
time_t t = s.count();
cout << ctime(&t) << "\n";
cin.ignore(1);
}
Every compiler except Visual Studio 2017 prints the correct time. The output of Visual Studio is:
Tue Jan 6 07:28:21 1970
the MinGW Output:
Sun Feb 03 18:01:38 2019
Is there any way to fix the code so that it works in all compilers correctly? I need high_resolution_clock to have access to milliseconds.
high_resolution_clock is an alias for the clock with the highest resoultion availavle:
Class std::chrono::high_resolution_clock represents the clock with the smallest tick period provided by the implementation. It may be an alias of std::chrono::system_clock or std::chrono::steady_clock, or a third, independent clock.
This could explain the different times you get on different compilers.
steady_clock Does not guarantee to give a time that makes sense, but is good for keeping track time:
This clock is not related to wall clock time (for example, it can be time since last reboot), and is most suitable for measuring intervals.
Is there any way to fix the code so that it works in all compilers correctly? I need high_resolution_clock to have access to milliseconds.
system_clock represents the clock of your OS:
Class std::chrono::system_clock represents the system-wide real time wall clock.
It may not be monotonic: on most systems, the system time can be adjusted at any moment. It is the only C++ clock that has the ability to map its time points to C-style time, and, therefore, to be displayed (until C++20).
If you need the milliseconds of a date or timepoint then use std::chrono::system_clock but if you just need to keep track of passed time, use std::chrono::high_resolution_clock.
To get the number of milliseconds since the start of system_clock:
auto timePoint = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>
(timePoint.time_since_epoch());
std::cout << "since epoch: " << ms.count() << " ms";
above snippet should work across most operating systems and compilers, although it is not guaranteed that time_since_epoch returns the time since 1970 but only to return the time since the clocks epoch, which in most cases is your desired behaviour.
The code assumes that time_since_epoch() returns the number of seconds since January 1, 1970 – so the value would be assignable to a variable time_t.
That assumption is wrong. time_since_epoch() can return any unit. In fact, high_resolution_clock is not designed to retrieve an absolute time and date. It's meant for performance measurements in the micro and nano seconds range.
In order to retrieve an absolute time / date, use system_clock. The class has a static method to create a time_t value:
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
using namespace chrono;
int main()
{
time_point<system_clock> now = system_clock::now();
time_t now_time = system_clock::to_time_t(now);
cout << ctime(&now_time) << "\n"
}
Update
To get the milliseconds since Jan 1, 1970:
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
using namespace chrono;
int main()
{
system_clock::time_point epochStart = system_clock::from_time_t(0);
long long epochStartMs = duration_cast<milliseconds>(epochStart.time_since_epoch()).count();
system_clock::time_point timePoint = system_clock::now();
long long timePointMs = duration_cast<milliseconds>(timePoint.time_since_epoch()).count();
long long durMs = timePointMs - epochStartMs;
cout << "Since 1st Jan 1970: " << durMs << " ms" << "\n";
}
For most systems, epochStartMs will probably be 0. But I think the standard doesn't guarantee that system_clock has it's epoch start on Jan 1, 1970.
This answer shows how to parse a string to a std::chrono::time_point, as follows:
std::tm tm = {};
std::stringstream ss("Jan 9 2014 12:35:34");
ss >> std::get_time(&tm, "%b %d %Y %H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
If I want to create a std::chrono::time_point from a (Gregorian) calendar date whose year, month, and day-of-month are known at compile time, is there any simpler way than parsing it from a string as suggested above?
Yes, you can do the entire computation at compile time, creating a constexpr system_clock::time_point using Howard Hinnant's date/time library.
#include "date/date.h"
#include <chrono>
int
main()
{
using namespace date;
using namespace std::chrono;
constexpr system_clock::time_point tp = sys_days{January/9/2014} + 12h + 35min + 34s;
static_assert(tp == system_clock::time_point{1389270934s}, "");
}
This is assuming that the date/time is UTC. If it isn't, you will have to manually add/subtract the UTC offset to make it so. As time zone rules are changed at the whim of politicians all the time, there is little hope in making them constexpr. Even historical time zone rules are updated when misunderstandings come to light.
Also this program will port to C++20 by dropping #include "date/date.h" and using namespace date;. Also using Howard Hinnant's date/time library requires C++14 constexpr muscle. C++11 constexpr is not sufficient (but you can do it at run-time, dropping the constexpr and static_assert).
If you have c++20, or will use Howard Hinnant date/time library, then Howard Hannant's answer is better, as it gives you a constexpr time_point.
However, if one doesn't yet have c++20 and wants to avoid adding more external libraries, then this answer is still useful.
You can set the members of the std::tm individually in the initializer, to avoid parsing a string.
// 9th January, 2014
#define DAY 9
#define MONTH 1
#define YEAR 2014
std::tm tm = { /* .tm_sec = */ 0,
/* .tm_min = */ 0,
/* .tm_hour = */ 0,
/* .tm_mday = */ (DAY),
/* .tm_mon = */ (MONTH) - 1,
/* .tm_year = */ (YEAR) - 1900,
};
tm.tm_isdst = -1; // Use DST value from local time zone
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
The designated initializers are commented out since they are only available in C++20 (though gcc has supported trivial designated initializers as an extension for some time and would work with this case). The fields initialized to zero could be omitted if one had full C++20 designated initializers and wanted midnight on the target date.
It is important to note that mktime will interpret the tm as local time, not GMT nor UTC. If tm_isdst is not set to -1, it will be local standard time, even if daylight savings (summer time) would be in use in the local time zone for the time specified.
Producing a UTC time point from a std::tm, a problem shared with your example, is addressed in other questions, such as Easy way to convert a struct tm (expressed in UTC) to time_t type
This works with C++11 and above:
#include <chrono>
std::chrono::system_clock::time_point
createDateTime(int year,
int month,
int day,
int hour,
int minute,
int second) // these are UTC values
{
tm timeinfo1 = tm();
timeinfo1.tm_year = year - 1900;
timeinfo1.tm_mon = month - 1;
timeinfo1.tm_mday = day;
timeinfo1.tm_hour = hour;
timeinfo1.tm_min = minute;
timeinfo1.tm_sec = second;
tm timeinfo = timeinfo1;
time_t tt = toUTC(timeinfo);
return std::chrono::system_clock::from_time_t(tt);
}
time_t toUTC(std::tm& timeinfo)
{
#ifdef _WIN32
std::time_t tt = _mkgmtime(&timeinfo);
#else
time_t tt = timegm(&timeinfo);
#endif
return tt;
}
Taken from ApprovalTests/utilities/DateUtils.cpp
I have to instantiate an object of a custom library class that takes nanoseconds since 'epoch' in UTC time to construct:
class utc_time
{
public:
utc_time(TYPE nanoseconds_since_epoch):
_nanoseconds_since_epoch(nanoseconds_since_epoch){}
private:
TYPE _nanoseconds_since_epoch;
};
what I have as my input is nanoseconds since 'midnight' in UTC time. Naturally, I need to get the epoch till last midnight nanoseconds(in UTC) to add it to my input and supply it to my class constructor.
I know we have gtime that may be helpful, but I dont know how to extract the required information.
I appreciate your clues
In C++11 and later, <chrono> can be used to do this very easily:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
using namespace std;
using days = duration<int, ratio<86400>>;
nanoseconds last_midnight =
time_point_cast<days>(system_clock::now()).time_since_epoch();
cout << last_midnight.count() << '\n';
}
In deed, nanoseconds since Epoch = nanoseconds since midnight + 1e9 * calendar time of last midnight. You lack the latter value. You can built it with a conjunction of ::gmtime() and ::mktime().
#include <ctime>
std::time_t last_midnight()
{
// compute "now"
std::tm& tm = *::gmtime(NULL);
// move it to "last midnight"
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
// get time_t back
return ::mktime(&tm);
}
You may find interest in using ::gmtime_r() (re-entrant version) instead of ::gmtime().
I've got a problem with getting actual system time with milliseconds. The only one good method I found is in Windows.h, but I can't use it. I'm supposed to use std::chrono. How can I do this?
I spent a lot of time trying to google it, but I found only second-precision examples.
I'm trying to get string like this:
[2014-11-25 22:15:38:449]
Using code from this answer:
#include <chrono>
#include <ctime>
#include <iostream>
template <typename Duration>
void print_time(tm t, Duration fraction) {
using namespace std::chrono;
std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%03u]\n", t.tm_year + 1900,
t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
static_cast<unsigned>(fraction / milliseconds(1)));
// VS2013's library has a bug which may require you to replace
// "fraction / milliseconds(1)" with
// "duration_cast<milliseconds>(fraction).count()"
}
int main() {
using namespace std;
using namespace std::chrono;
system_clock::time_point now = system_clock::now();
system_clock::duration tp = now.time_since_epoch();
tp -= duration_cast<seconds>(tp);
time_t tt = system_clock::to_time_t(now);
print_time(*gmtime(&tt), tp);
print_time(*localtime(&tt), tp);
}
One thing to keep in mind is that the fact that the timer returns values of sub-millisecond denominations does not necessarily indicate that the timer has sub-millisecond resolution. I think Windows' implementation in VS2015 may finally be fixed, but the timer they've been using to back their chrono implementation so far has been sensitive to the OS timeBeginPeriod() setting, displaying varying resolution, and the default setting is I think 16 milliseconds.
Also the above code assumes that neither UTC nor your local timezone are offset from the epoch of std::chrono::system_clock by a fractional second value.
Example of using Howard's date functions to avoid ctime: http://coliru.stacked-crooked.com/a/98db840b238d3ce7
This answer still uses a bit of C API but is only used in the function, so you can forget about it:
template<typename T>
void print_time(std::chrono::time_point<T> time) {
using namespace std;
using namespace std::chrono;
time_t curr_time = T::to_time_t(time);
char sRep[100];
strftime(sRep,sizeof(sRep),"%Y-%m-%d %H:%M:%S",localtime(&curr_time));
typename T::duration since_epoch = time.time_since_epoch();
seconds s = duration_cast<seconds>(since_epoch);
since_epoch -= s;
milliseconds milli = duration_cast<milliseconds>(since_epoch);
cout << '[' << sRep << ":" << milli.count() << "]\n";
}
This is merely a rewrite of the code that bames53, but using strftime to shorten the code a bit.
std::chrono give you utilities to represent a point in time or the elapsed duration between two points in time. It allows you to get information about these time intervals.
It does not provide any calendar information. Unfortunately, at this time there are no tools in the C++ standard for these. boost::date_time may be helpful here.
Did anybody notice that to_time_t rounds the seconds, instead of truncating
auto now = system_clock::now();
time_t secs = system_clock::to_time_t(now);
now {_MyDur={_MyRep=15107091978759765 } }
secs = 1510709198
so when you tack on the milliseconds
auto tse = now.time_since_epoch();
auto now_ms = duration_cast<milliseconds>(tse);
auto now_s = duration_cast<seconds>(tse);
auto jst_ms = now_ms - now_s;
DWORD msecs = jst_ms.count();
msecs = 875
secs should be 1510709197, but look at now_s, it's right
now_s {_MyRep=1510709197 }