How to sleep until next Sunday - c++

How can I sleep until next Sunday using boost? Can i convert boost::gregorian::date object to something that boost::this_thread::sleep_until can handle? Is it possible?
#include <boost/date_time.hpp>
int main()
{
boost::gregorian::date current_date(boost::gregorian::day_clock::local_day());
boost::gregorian::greg_weekday next_sunday_date(boost::gregorian::Sunday);
boost::gregorian::date next_weekday_date = next_weekday(current_date, next_sunday_date);
// ...
}

Here's what I came up with.
Note that I made the code generally more readable. This is important, not just for future maintenance, but also because it will allow you to "see the forest for the trees" - in turn allowing you to remember the important concepts mentally.
At least, that helps me.
Edit DyP contributed a way to use sleep_until (which would behave more accurately in rare circumstances, e.g. where the clock would change during the sleep).
#include <boost/date_time.hpp>
#include <boost/date_time/time_clock.hpp>
#include <iostream>
#include <thread>
#include <chrono>
int main()
{
using namespace boost::gregorian;
using boost::posix_time::ptime;
using clock = boost::posix_time::microsec_clock; // or: boost::posix_time::second_clock;
auto today = date(day_clock::local_day());
auto at_sunday = greg_weekday(Sunday);
auto next_sunday = next_weekday(today, at_sunday);
#if 1
auto as_tm = to_tm(next_sunday);
auto as_time_t = mktime(&as_tm);
auto as_time_point = std::chrono::system_clock::from_time_t(as_time_t);
std::this_thread::sleep_until(as_time_point);
#else
auto duration = (ptime(next_sunday) - clock::local_time());
auto msecs = duration.total_milliseconds();
std::cout << msecs << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(msecs));
#endif
}
See it compiling on Coliru (obviously times out)

This sounds unstable. What if the user turns the computer off or goes into hibernation, or just does a restart?
I would do this in one of two ways:
Add a scheduled task(or whatever the windows/osx terminology is) / cronjob (linux) and set it to run on Sunday.
Add it to autostart and periodically(once per 10/30/60 minutes) check if it's Sunday.
Both ways handle restart/shut off/hibernation better than sleeping for 5 days.

Related

Adding over 30 days to 1900-01-01

How can I add over 30 days in C++ to 1900-01-01 date approx. over 1000 days and then format the time_t after the addition to get a non-broken date.
This is what I have tried so far:
int tmp = 1000;
struct std::tm tm;
std::istringstream ss("1900-01-01");
ss >> std::get_time(&tm, "%Y-%m-%d");
tm.tm_mday = tm.tm_mday + tmp;
return mktime(&tm);
In addition to Joseph Larson's very good suggestion to check out the date/time library to use, I'll show how you could get further using your current idea.
You also have much support in std::chrono nowadays so read about that too.
You try to add the days in the wrong domain, to std::tm. Instead, convert the std::tm to time_t and add the days to that - then convert the result back to std::tm.
Example:
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
int main() {
int days = 1000;
std::tm tm{};
std::istringstream ss("1900-01-01");
if(ss >> std::get_time(&tm, "%Y-%m-%d")) {
tm.tm_isdst = -1; // let mktime "guess" if DST is effect
// convert to time_t and add 1000 days. 1 day = 24*60*60 seconds
std::time_t result = std::mktime(&tm) + days * 60*60*24;
// back to std::tm
tm = *std::localtime(&result);
// print result
std::cout << std::put_time(&tm, "%Y-%m-%d") << '\n';
}
}
Note: This technique will sometimes get the wrong answer. If for the computer's local time zone the UTC offset at 1900-01-01 is greater than it is at 1900-01-01 + days, then the result will be one day less than it should. This happens (for example) with the IANA time zone America/Anchorage with days == 232. It happens again with Africa/Cairo at days == 273.
A better option is clearly to use the facilities in chrono or Howard Hinnant's date library as demonstrated by Howard.
Date/time handling in C++ is awkward as awkward can be. Howard Hinnant has a great library you may want to look at:
https://github.com/HowardHinnant/date
The problem is complicated. If you use local dates, you can't add a fixed amount of time due to daylight savings time and leap seconds. You could use GMT, but you're still subject to leap seconds.
But Howard's library make make this much easier for you. I'd take a peek.
If you are using the latest Visual Studio 2019, then you have C++20 <chrono> which can solve this problem without the errors associated with the mktime/localtime technique demonstrated in Ted Lyngmo's answser.
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
// Hold the amount to add in the type std::chrono::days (a chrono duration)
std::chrono::days days{1000};
// std::chrono::sys_days is a Unix Time chrono::time_point with precision days
std::chrono::sys_days tp;
std::istringstream ss("1900-01-01");
if(ss >> std::chrono::parse("%F", tp)) {
// No need to involve time zones.
// Just add and print out
std::cout << tp + days << '\n'; // 1902-09-28
}
}
This program has the same behavior and output as Ted's answser. But if there's no need to read the "constant" 1900-01-01 out of a stream, then we can do even better. C++20 can make 1900-01-01 a compile-time constant:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono_literals;
std::chrono::days days{1000};
constexpr std::chrono::sys_days tp = 1900y/01/01; // Compile-time date literal
// Just add and print out
std::cout << tp + days << '\n'; // 1902-09-28
}
These solutions don't involve time zones at all. It is simply adding a number of days to a date. The simplicity makes for efficient code and reduces the chance for errors associated with increased complexity.
If you don't have the latest Visual Studio 2019, or otherwise don't have access to C++20, you can use Howard's free, open-source, header-only "date.h" C++20 chrono preview library referred to in Joseph's answer with nearly identical syntax.
#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date::literals;
date::days days{1000};
constexpr date::sys_days tp = 1900_y/01/01; // Compile-time date literal
// Just add and print out
using date::operator<<;
std::cout << tp + days << '\n'; // 1902-09-28
}
The C++20 chrono additions are in namespace date instead of namespace std::chrono.
The year literal is spelled _y instead of y.
The time_point streaming operators won't be found by ADL and have to be manually exposed in namespace date.

Why does difference in two chrono time points result in seconds?

I have the following code:
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main()
{
using my_timepoint = time_point<high_resolution_clock, nanoseconds>;
my_timepoint now = system_clock::now();
my_timepoint then = system_clock::now() - seconds{1};
duration<double> my_dur = now - then;
cout << my_dur.count();
}
Here my_timepoint is expressed in nanoseconds still I get output of this code as 1. Why is it not 1e+09? How does the difference in two time points evaluated?
The duration template takes a ratio argument as described here:
https://en.cppreference.com/w/cpp/chrono/duration
The code posted is using the default value (1 tick every 1 second), so naturally when you ask it for count(), it will return just 1, to represent the number of ticks that have elapsed.
You can construct a duration object that uses a different ratio, then you'll get 1e+09:
duration<double, std::ratio<1, 1000000000>> my_dur = now - then;

Process Timing Discrepancies

Let me start by saying, I am not a skilled C++ programmer, I have just begun that journey and am working in a Win 10 environment using Code::Blocks as my ide. I am starting to learn C++ by coding solutions to the Euler Project problems. I used these problems to start learning Python several years ago, so I have at least one Python solution for the first 50+ problems. In doing these problems in Python, I learned that as my skill improves, I can formulate better solutions. When learning Python, I used a trial & error approach to improving my code until I became aware of the python tools for timing my code. Once, I defined a convenient and consistent timing method, my coding improved dramatically. Since, I am beginning this journey now with C++ I decided I would be proactive and create a consistent method for timing the code execution. To do this, I have decided to utilize the C++ chrono library and have defined two different approaches that seemingly should produce the same time results. However as the tile to this question implies they don't.
So here's my question: Why don't the following two approaches yield the same results?
Approach # 1
This method provides a timing for the do some stuff segment of slightly over 3 seconds, but less than the CODE::BLOCKS execution time report of 3.054 seconds. I certainly understand these differences based on the program flow. So this approach seems to give good result. The issue I have with this approach is I need to copy & paste the timing code into each .cpp file I want to time, which seems sloppy.
Output using this method looks like the following:
Elapsed time in seconds : 3.00053 sec
Process returned 0 (0x0) execution time : 3.151 s
#include <iostream>
#include <chrono>
#include <unistd.h>
using namespace std;
using Clock = chrono::steady_clock;
using TimePoint = chrono::time_point<Clock>;
// Functions
TimePoint get_timestamp();
double get_duration(TimePoint, TimePoint);
int main()
{
//auto start = chrono::steady_clock::now();
auto start_t = get_timestamp();
//cout << "Start is of type " << typeid(start).name() << "\n";
// do some stuff
sleep(3);
auto end_t = get_timestamp();
//double tme_secs = chrono::duration_cast<chrono::nanoseconds>(end - start).count()/1000000000.0000;
double tme_secs = get_duration(start_t, end_t)/1000000000;
cout << "Elapsed time in seconds : " << tme_secs << " sec";
return 0;
}
TimePoint get_timestamp(){
return Clock::now();
}
double get_duration(TimePoint start, TimePoint end){
return chrono::duration_cast<chrono::nanoseconds>(end - start).count()*1.00000000;
}
Approach #2
In this approach, I attempted to create a ProcessTime class which could be included in files that I want to time and provide a cleaner method. The problem with this approach is I get timing report in the nano seconds, which does not reflect the process being timed. Here is my implementation of this approach.
output using this method looks like the following:
Elapsed time: 1.1422e+06 seconds
Process returned 0 (0x0) execution time : 3.148 s
ProcessTime.h file
#ifndef PROCESSTIME_H_INCLUDED
#define PROCESSTIME_H_INCLUDED
#include <chrono>
using namespace std;
using Clock = chrono::steady_clock;
using TimePoint = chrono::time_point<Clock>;
class ProcessTime{
public:
ProcessTime();
double get_duration();
private:
TimePoint proc_start;
};
#endif // PROCESSTIME_H_INCLUDED
ProcessTime.cpp file
#include "ProcessTime.h"
#include <chrono>
using namespace std;
using Clock = chrono::steady_clock;
using TimePoint = chrono::time_point<Clock>;
ProcessTime::ProcessTime(){
TimePoint proc_start = Clock::now();
}
double ProcessTime::get_duration(){
TimePoint proc_end = Clock::now();
return chrono::duration_cast<chrono::nanoseconds>(proc_end - ProcessTime::proc_start).count()*1.00000000;
}
main.cpp file:
#include <iostream>
#include "ProcessTime.h"
#include <unistd.h>
using namespace std;
int main()
{
ProcessTime timer;
// Do some Stuff
sleep(3);
double tme_secs = timer.get_duration()/1000000000;
cout << "Elapsed time: " << tme_secs << " seconds";
return 0;
}
This is incorrect:
ProcessTime::ProcessTime(){
TimePoint proc_start = Clock::now();
}
You are setting a local variable named proc_start, and then the constructor ends. You did not set the actual member variable of ProcessTime.
One fix (and the preferred method) is to use the member-initialization list:
ProcessTime::ProcessTime() : proc_start(Clock::now()) {}
or if you knew nothing about the member-initialization list, the code would look like this to assign the value.
ProcessTime::ProcessTime(){
proc_start = Clock::now();
}

Get current time of day in c++

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
}

How do you print the current system time with milliseconds in C++11?

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 }