c++ time manipulation using time_t in Win platform - c++

Well i want to manipulate time with a time_t variable in this way:
time1 = get the current time as time_t (say it's 9:30 now)
use SYSTEMTIME to see if we passed 10:00
if we didn't pass 10:00 : evaluate what (time_t)time2 would be in 10:00.
and set time3 = time2 - time1 in order to get in seconds how much is left till 10:00.
I don't want to use boost because i don't want to link my application to it.
I hope i made it clear that i want to check what's the time now and what it would be
in say 10:00 to get the time difference between now and a pre defined time (not date).

time_t time1;
time(&time1);
tm time0 = *localtime( &time1);
if (time0.tm_hour == 22 && time0.tm_min == 0)
; // it 10PM
else
{
// force time0 to 10PM
time0.tm_hour = 22;
time0.tm_min = 0;
time_t time2 = mktime(&time0);
}

Either use GetSystemTime() so everything is Windows, or call time() to get the current time using the C runtime values.

Related

Convert date to unix time stamp in c++

As some websites that convert those unix time stamps say, the stamp of
2013/05/07 05:01:00 (yyyy/mm/dd, hh:mm:ss) is 1367902860.
The way I do it in C++, the stamp differs from the date.
Here is the code:
time_t rawtime;
struct tm * timeinfo;
int year=2013, month=5, day=7, hour = 5, min = 1, sec = 0;
/* get current timeinfo: */
time ( &rawtime ); //or: rawtime = time(0);
/* convert to struct: */
timeinfo = localtime ( &rawtime );
/* now modify the timeinfo to the given date: */
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1; //months since January - [0,11]
timeinfo->tm_mday = day; //day of the month - [1,31]
timeinfo->tm_hour = hour; //hours since midnight - [0,23]
timeinfo->tm_min = min; //minutes after the hour - [0,59]
timeinfo->tm_sec = sec; //seconds after the minute - [0,59]
/* call mktime: create unix time stamp from timeinfo struct */
date = mktime ( timeinfo );
printf ("Until the given date, since 1970/01/01 %i seconds have passed.\n", date);
The resulting time stamp is
1367899260, but not 1367902860.
What is the problem here? Even if I change to hour-1 or hour+1, it does not match. EDIT: Well yes if i add 1 to hour, it works. previously also added 1 to minutes.
You must use timegm() instead of mktime(), and that's all. Because mktime is for localtime and timegm for UTC/GMT time.
Converting Between Local Times and GMT/UTC in C/C++
Do you have daylight saving time when you are from? The tm::tm_isdst parameter is a flag for daylight saving time. This will get filled by the localtime call based on where you are and the time of year and you do not reset it. So even if both you and the web page are using the same time, if you have the daylight saving flag set and the web page doesn't then you will end up different by 1 hour.
Note you don't really need the localtime call. You can just fill in all the parts manually because tm::tm_wday and tm::tm_yday are ignored by mktime. Check out http://www.cplusplus.com/reference/ctime/tm/ and http://www.cplusplus.com/reference/ctime/mktime/
Don't use a pointer to localtime. Save the actual value
struct tm timeinfo;
...
timeinfo = *localtime(&rawtime);
...
date = mktime(&timeinfo);
You don't know what else may be using the pointer that localtime is returning. mktime might possibly be using it.
It looks like the website is assuming the time is in the UTC timezone, and your computer is set to some other timezone.
You can call gmtime rather than localtime to use UTC for that; but I've just noticed that you're not actually using localtime to do anything except get a pointer to a tm. You'd be better off declaring a local tm; the one used by localtime could be reused whenever you call another time library function.
Unfortunately, there's no standard variation of mktime using UTC. If you want UTC, your options are:
Set the timezone using setenv("TZ", "", 1);. Note that this affects the whole program, so can be awkward if you also need to deal with local time.
Use a library like Boost.DateTime, which is slightly better at handling dates and timezones than the C library.
mktime() converts local calendar time to a time since epoch as a time_t object, so your result will be different from the website's if you are in a different time-zone. The website takes 2013/05/07 05:01:00 as a UTC time. The same code on my machine has a result of 1367874060, which is 8 hour away from the website's value. I'm in UTC+8:00 time-zone, so mktime() on my machine takes the input 2013/05/07 05:01:00 as a UTC+8:00 time, thus causing the difference.
PS: localtime() returns a pointer to a static internal struct tm object. The structure may be shared between gmtime(), localtime(), and ctime(), and may be overwritten on each invocation. So it's a better practice to have your own local copy of a struct tm object.

fully separated date with milliseconds from std::chrono::system_clock

My current pattern (for unix) is to call gettimeofday, cast the tv_sec field to a time_t, pass that through localtime, and combine the results with tv_usec. That gives me a full date (year, month, day, hour, minute, second, nanoseconds).
I'm trying to update my code to C++11 for portability and general good practice. I'm able to do the following:
auto currentTime = std::chrono::system_clock::now( );
const time_t time = std::chrono::system_clock::to_time_t( currentTime );
const tm *values = localtime( &time );
// read values->tm_year, etc.
But I'm stuck on the milliseconds/nanoseconds. For one thing, to_time_t claims that rounding is implementation defined (!) so I don't know if a final reading of 22.6 seconds should actually be 21.6, and for another I don't know how to get the number of milliseconds since the previous second (are seconds guaranteed by the standard to be regular? i.e. could I get the total milliseconds since the epoch and just modulo it? Even if that is OK it feels ugly).
How should I get the current date from std::chrono::system_clock with milliseconds?
I realised that I can use from_time_t to get a "rounded" value, and check which type of rounding occurred. This also doesn't rely on every second being exactly 1000 milliseconds, and works with out-of-the-box C++11:
const auto currentTime = std::chrono::system_clock::now( );
time_t time = std::chrono::system_clock::to_time_t( currentTime );
auto currentTimeRounded = std::chrono::system_clock::from_time_t( time );
if( currentTimeRounded > currentTime ) {
-- time;
currentTimeRounded -= std::chrono::seconds( 1 );
}
const tm *values = localtime( &time );
int year = values->tm_year + 1900;
// etc.
int milliseconds = std::chrono::duration_cast<std::chrono::duration<int,std::milli> >( currentTime - currentTimeRounded ).count( );
Using this free, open-source library you can get the local time with millisecond precision like this:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << make_zoned(current_zone(),
floor<milliseconds>(system_clock::now())) << '\n';
}
This just output for me:
2016-09-06 12:35:09.102 EDT
make_zoned is a factory function that creates a zoned_time<milliseconds>. The factory function deduces the desired precision for you. A zoned_time is a pairing of a time_zone and a local_time. You can get the local time out with:
local_time<milliseconds> lt = zt.get_local_time();
local_time is a chrono::time_point. You can break this down into date and time field types if you want like this:
auto zt = make_zoned(current_zone(), floor<milliseconds>(system_clock::now()));
auto lt = zt.get_local_time();
local_days ld = floor<days>(lt); // local time truncated to days
year_month_day ymd{ld}; // {year, month, day}
time_of_day<milliseconds> time{lt - ld}; // {hours, minutes, seconds, milliseconds}
// auto time = make_time(lt - ld); // another way to create time_of_day
auto y = ymd.year(); // 2016_y
auto m = ymd.month(); // sep
auto d = ymd.day(); // 6_d
auto h = time.hours(); // 12h
auto min = time.minutes(); // 35min
auto s = time.seconds(); // 9s
auto ms = time.subseconds(); // 102ms
Instead of using to_time_t which rounds off you can instead do like this
auto tp = std::system_clock::now();
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch());
auto t = (time_t)(s.count());
That way you get the seconds without the round-off. It is more effective than checking difference between to_time_t and from_time_t.
I read the standard like this:
It is implementation defined whether the value is rounder or truncated, but naturally the rounding or truncation only occurs on the most detailed part of the resulting time_t. That is: the combined information you get from time_t is never more wrong than 0.5 of its granularity.
If time_t on your system only supported seconds, you would be right that there could be 0.5 seconds systematic uncertainty (unless you find out how things were implemented).
tv_usec is not standard C++, but an accessor of time_t on posix. To conclude, you should not expect any rounding effects bigger than half of the smallest time value difference your system supports, so certainly not more than 0.5 micro seconds.
The most straight forward way is to use boost ptime. It has methods such as fractional_seconds()
http://www.boost.org/doc/libs/1_53_0/doc/html/date_time/posix_time.html#date_time.posix_time.ptime_class
For interop with std::chrono, you can convert as described here: https://stackoverflow.com/a/4918873/1149664
Or, have a look at this question: How to convert std::chrono::time_point to calendar datetime string with fractional seconds?

Adding two epoch millseconds in C++

My goal is to determine expiry of an item to when it was acquired(bought) and when it is sold.There is a TTL value associated with each of the item.
I am doing following :
time_t currentSellingTime;
long currentSystemTime = time(&currentSellingTime); // this gives me epoch millisec of now()
long TTL = <some_value>L;
long BuyingTime = <some_value> // this is also in epoch millsec
if(currentSystemTime > TTL+BuyingTime))
{
//throw exception
// item is expired
}
My question is how to sum two epoch millisec and compare it with another epoch millsec in C++
There may be some misconceptions on how time() works:
epoch time as given by time() is expressed in seconds, not millseconds
time returns the current time value and can optionally set current time in the variable given as its sole argument. This means that
long currentSystemTime = time(&currentSellingTime);
will set both currentSystemTime and currentSellingTime to the current time, and that's probably not what you intend to do... You should probably do
long currentSystemTime = time(NULL);
or
time(&currentSellingTime);
but the "double form" you are using is quite suspicious. For completeness' sake the MS Help reference for time()
You want to use another function, as as previously pointed out, time() returns seconds. Try:
#include <time.h>
long current_time() {
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return t.tv.sec * 1000l + t.tv_nsec / 1000000l;
}
Your code should work then. This approach is also POSIX compatible. Example usage:
const long TTL = 100;
long start_time = current_time();
while (!(current_time() > start_time + TTL))
{
// do the stuff that can expire
}
note: I know that the condition in the while loop can be constructed differently, but this way it is more like "until not expired".

difference seen in difftime and strftime values

I'm seeing a difference in time functions and was wondering what was the reason.
currently, I'm using localtime, mktime, strftime and difftime:
time_t ltime;
ltime = time(NULL);
StartTM = localtime(&ltime);
time_t time1 = mktime(StartTM );
char startbuffer [128];
strftime( start_buffer, 128, "%H:%M:%S", StartTM );
<<Do some stuff, take some time >>>
time_t ttime;
ttime = time(NULL);
StopTM = localtime(&ttime);
time_t time2 = mktime(StopTM );
char stop_buffer [128];
strftime( stop_buffer, 128, "%H:%M:%S:", StopTM );
double wtinsec = difftime(time2, time1);
Executed, the output looks like this:
Stop buffer=08:46:18
Start buffer=08:44:11
wtinsec=129
Subtracting start from stop by hand, the length of time is 2:07, however the total number of seconds (difftime) says 2:09. As both times are using the same raw data (time1, time2) for both calculations, my initial thoughts was combination of lack of precision in the strftime conversion and difftime is the cause of this.
But the difference is not constant. If the time between the 2 local calls is small (like 10 seconds) there is no difference. However, as the time between the 2 time calls gets longer, the difference in time totals becomes larger. At 2 mins, its 2 seconds at 5 mins its 4 seconds and so on...
Any reason why this is happening and is there anything more accurate (in C++) preferably in micro/milliseconds that can track time of day and subtract one from another?
Thanks.
The values in ltime and time1 should be identical; the round trip through localtime() and mktime() should give you the answer you started with. Similarly, of course, for ttime and time2.
This C code demonstrates the expected behaviour. You need to look hard at your code to find out what is going wrong.
#include <stdio.h>
#include <time.h>
#include <unistd.h>
int main(void)
{
time_t ltime = time(NULL);
struct tm *start = localtime(&ltime);
time_t time1 = mktime(start);
char startbuffer[128];
strftime(startbuffer, sizeof(startbuffer), "%H:%M:%S", start);
printf("lt = %10lu, t1 = %10lu, time = %s\n",
(unsigned long)ltime, (unsigned long)time1, startbuffer);
sleep(10);
time_t ttime = time(NULL);
struct tm *finis = localtime(&ttime);
time_t time2 = mktime(finis);
strftime(startbuffer, sizeof(startbuffer), "%H:%M:%S", finis);
printf("lt = %10lu, t1 = %10lu, time = %s\n",
(unsigned long)ttime, (unsigned long)time2, startbuffer);
printf("diff time = %.2f\n", difftime(time2, time1));
return(0);
}
Sample output (from Mac OS X 10.7.5):
lt = 1358284665, t1 = 1358284665, time = 13:17:45
lt = 1358284675, t1 = 1358284675, time = 13:17:55
diff time = 10.00
I recommend looking at the values in your code, similar to the way I did. You might (or might not) print out the contents of the struct tm structures. It would be worth making a function to handle the 7-line block of repeated code; you'll need it to return time1 and time2, of course, so you can do the difference in the 'main' code. Also remember that localtime() may return the same pointer twice; you can't reliably use the start time structure after you've called localtime() with the finish time.

See if a timestamp is between a specific hour

I have a lot of timestamps, and data associated with it. I want to retrieve data that came from say 0800 - 0900.. What is the way to check if a timestamp falls between that?
How should i write a function that inputs two hours and returns a list of timestamps that falls inside those hours, regardless of what day it is?
like
std::list<uint32_t> getTimestampsBetween(uint16_t min_hour, uint16_t max_hour)
{
if(timestamp from list of timestamp is between min_hour and max_hour)
add it to list;
return list;
}
use localtime to convert timestamp to struct tm and check if the tm_hour attribute of the structure falls within the specified window.
Look into time.h for more information.
It depends on the format of the timestamps, but if they're time_t, you
can use mktime to convert a given tm to a time_t, and difftime
to compare two time_t. Something along the lines of:
bool
timeIsInInterval( time_t toTest, int minHour, int maxHour )
{
time_t now = time( NULL );
tm scratch = *localtime( &now );
scratch.tm_sec = scratch.tm_min = 0;
scratch.tm_hour = minHour;
time_t start = mktime( &scratch );
scratch.tm_hour = maxHour;
time_t finish = mktime( &scratch );
return difftime( toTest, start ) >= 0.0
&& difftime( toTest, finish ) < 0.0;
}
(In practice, toTest >= start && toTest < finish is probably
sufficient. Although the standard allows much more, I don't know of any
implementations where time_t is not an integral type containing the
number of seconds since some magic date.)
This supposes, of course, that you're looking for the times between the
two hours today. If you want some arbitrary date, it's easy to modify.
If you want any date, you need to do the reverse: convert the timestamps
to a tm, and compare the tm_hour fields.