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.
Related
I'm using C++14 and the famous Date library by #HowardHinnant
I'm trying to convert a GMT (UTC) time to the time inside of some timezone. I need to have it in the tm struct.
All seems good except I can't seem to properly construct the hms object. My template arguments mismatch.
tm Time_hrv::gmtTM_to_timezoneTM(const tm& timeTM_gmt, const std::string& wanted_timezoneStr){
assert(timeTM_gmt.tm_year < 1000);// the year of tm should be relative to 1900. For example, 2020 should be 120.
assert(timeTM_gmt.tm_mon < 12);// [0,11]
assert(timeTM_gmt.tm_mday > 0 && timeTM_gmt.tm_mday<=31);// [0,31]
time_t timeT_gmt = Time_hrv::timeTM_to_timeT(timeTM_gmt);
auto chronoTime_gmt = std::chrono::system_clock::from_time_t(timeT_gmt);
const date::time_zone* wanted_timeZone = timeZone_fromString(wanted_timezoneStr);
//https://stackoverflow.com/a/70759851/9007125
//NOTICE: local_time isn't necessarily the computer's local time.
//It is a local time that has not yet been associated with a time zone.
//When you construct a zoned_time, you associate a local time with a time zone.
auto lt = wanted_timeZone->to_local(chronoTime_gmt);
auto localDay = date::floor<date::days>(lt);
date::year_month_day ymd{ localDay };
date::hh_mm_ss<std::chrono::milliseconds> hms{ lt - localDay }; //<--- error here
tm result = {0};
result.tm_year = int{ymd.year()} - 1900;
result.tm_mon = unsigned{ymd.month()} -1;
result.tm_mday = unsigned{ymd.day()};
result.tm_hour = (int)hms.hours().count();
result.tm_min = (int)hms.minutes().count();
result.tm_sec = (int)hms.seconds().count();
return result;
}
This is chrono giving you a bad error message for a real problem: You are attempting to silently truncate a fine precision expression (lt - localDay) to a coarser precision (milliseconds).
The expression lt - localDay is a type that has precision of system_clock::duration, which is somewhere between microseconds and nanoseconds depending on your platform. This is true, even though the source (and thus the value) of chronoTime_gmt only has precision of seconds at run time.
The easiest fix is to recognize that anything coming from a tm is at best seconds precision by truncating to seconds precision early:
auto chronoTime_gmt = date::floor<std::chrono::seconds>
(std::chrono::system_clock::from_time_t(timeT_gmt));
Now chronoTime_gmt has type time_point<system_clock, seconds>. And therefore the later expression lt - localDay will also have type seconds, which will implicitly convert to the milliseconds precision of your hh_mm_ss.
A suggestion is to also use seconds for the template parameter of your hh_mm_ss since the milliseconds precision goes unused. This won't change correctness or performance of your code, but the reader of your code will no longer spend time wondering why you chose milliseconds and then didn't use it.
If I have hour of the day and day of the week as 1am and Monday. How can I convert these into a datetime value in C++? thanks in advance.
Regards,
Jack
may be this can help you:
boost.org
2am on Sunday occurs at least once a week (twice when switching to/from daylight saving!).
So you need the month and day in that month.
Time in standard C/C++ can be represented with std::tm
Structure holding a calendar date and time
std::tm tm;
tm.tm_wday = 1; // monday
tm.tm_hour = 1; // 1 am
How to get local time ?
#include <ctime>
...
time_t rawtime = time(&rawtime);
struct tm *tnow = localtime(&rawtime);
Maybe a simpler option would be to use C++11 time_point (must have compatible compiler)
system_clock::time_point now = system_clock::now();
then go back to a tm object
std::tm* tnow = localtime(now);
Time difference
struct tm diff = difftime(mktime(&tnow),mktime(&tm);
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.
I want to retrieve time zone from struct tm as the format below
2011-12-32 12:13:05 +0530(obtained using gtime)
I could get the first two sets but could not get the way getting the time zone value. Please let me know how it should get the time zone using c++ time.
Regards,
iSight
If you really want to use standard C library to get timezone, try using external variable 'timezone' declared in time.h. Keep in mind that its value is set after tzset() function call. Every time conversion function that depends on the timezone implicitly calls this function. As an alternative you can call tzset() explicitly.
The 'timezone' variable should be declared like this in time.h:
extern long timezone;
It contains time difference between local time and UTC in seconds.
Also you can use exern char* tzname[2] to get the symbolic timezone names for DST and non-DST periods.
You can not calculate the timezone information from struct tm directly, unless you know exactly the UTC time corresponding to time stored in that structure;
I think tm structure retrieved via time.h contains timezone information, if all you require is difference from GMT.
struct tm {
int tm_sec; /* seconds after the minute [0-60] */
int tm_min; /* minutes after the hour [0-59] */
int tm_hour; /* hours since midnight [0-23] */
int tm_mday; /* day of the month [1-31] */
int tm_mon; /* months since January [0-11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
long tm_gmtoff; /* offset from CUT in seconds */
char *tm_zone; /* timezone abbreviation */
};
Something like the following can help:
uint64_t diff;
{
time_t secs = time (NULL);
tm timeParts;
memset(&timeParts, 0, sizeof(timeParts));
tm *timeInfo = localtime_r( &secs, &timeParts );
diff = mktime( timeInfo );
memset(&timeParts, 0, sizeof(timeParts));
timeInfo = gmtime_r ( &secs, &timeParts );
diff -= mktime( timeInfo );
}
return diff;
Please note that this code does something else but it shows all the functions that you can use to retrieve information that you may require.
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.