Getting time difference using a time_t converted from a string - c++

I am trying to get the diff between two dates.
One date being right now and the other is a date converted to time_t from a string representation of a date.
My code is as follows
const char *time_details = "12/03/2014";
struct tm tm;
strptime(time_details, "%m/%d/%Y", &tm);
time_t mytime = mktime(&tm);
time_t now;
time(&now);
double seconds = difftime(now, mytime);
LOGG("now = %d", now);
LOGG("mytime = %d", mytime);
LOGG("unsigned int mytime = %d", (int)mytime);
My output looks like so:
now = 1417830679
mytime = -1
seconds = 1610001720
mytime always comes out to -1
And, the value for seconds is not correct either.

Add before use (and you might want to pick a different name for the variable)
memset(&tm, 0, sizeof(struct tm));
See Notes section in strptime(3)

Related

Convert a time (UTC ) given as a string to local time

I have a time string like this "132233" (Time only no date) and i want to convert it into local time.
So, in order to use the function localtime(), I first converted my string into time_t using mktime() (thanks to How to convert a string variable containing time to time_t type in c++? )and then printed the time after conversion using strftime as shown in (http://www.cplusplus.com/reference/ctime/strftime/)
I am getting a serious run time error. Can any one please tell me whats wrong. Thanks in advance
int main()
{
string time_sample="132233";
std::string s_hrs (time_sample.begin(), time_sample.begin()+2);
std::string s_mins (time_sample.begin()+2,time_sample.begin()+4);
std::string s_secs (time_sample.begin()+4,time_sample.begin()+6);
int hrs = atoi(s_hrs.c_str());
int mins = atoi(s_mins.c_str());
int secs = atoi(s_secs.c_str());
struct tm time_sample_struct = {0};
time_sample_struct.tm_hour = hrs;
time_sample_struct.tm_min = mins;
time_sample_struct.tm_sec = secs;
time_t converted_time;
converted_time = mktime(&time_sample_struct);
struct tm * timeinfo;
char buffer[80];
timeinfo = localtime(&converted_time);
strftime(buffer,80,"%I:%M:%S",timeinfo);
puts(buffer);
cout<<endl;
getch();
return 0;
}
Your problem is that if time_t is a 32 bit value, the earliest possible date it's capable of encoding (given a 1970-1-1 epoch) is 1901-12-13.
However you're not setting the date fields of your tm struct, which means it is defaulting to 0-0-0 which represents 1900-1-0 (since tm_day is 1-based, you actually end up with an invalid day-of-month).
Since this isn't representable by a 32-bit time_t the mktime function is failing and returning -1, a situation you're not checking for.
Simplest fix is to initialise the date fields of the tm struct to something a time_t can represent:
time_sample_struct.tm_year = 114;
time_sample_struct.tm_mday = 1;

how to convert an unsigned value to struct tm?

I am getting absolute time value like as follows,
1413399540000
1411047780000
1411574340000
How can I convert them to "struct tm" in c++?
Hi Joachim,
this is an input from GUI for accesslist time range and i tried the following,
typedef unsigned long long uint64_t;
uint64_t mytime;
struct tm *tm;
time_t realtime;
mytime = 1447862580005ULL;
realtime = (time_t) (mytime / 1000000);
printf ("The current local time is: %s", ctime(&realtime));
tm = localtime(&realtime);
printf ("The current local time is: %s", asctime(tm));
tm->tm_year +=1900;
tm->tm_mon +=1;
printf("%04d-%02d-%02d %02d:%02d:%02d\n",
tm->tm_year,tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
o/p :
The current local time is: Sat Jan 17 10:11:02 1970
The current local time is: Sat Jan 17 10:11:02 1970
1970-01-17 10:11:02
Looks confuse to me.Not sure how to verify the conversion got corect value or not.
1413399540000 looks like a number of milliseconds since unix epoch, namely 15.10.2014 18:59:00.
auto millisec = 1413399540000;
time_t time = millisec / 1000;
tm local;
localtime_r(&time, &local); // TODO: Check the errors.
tm utc;
gmtime_r(&time, &utc); // TODO: Check the errors.

Converting localtime to time_t (C++)

I creating date() function on C++ http://aliarth.lt/date.cpp and I got one problem with localtome_to_time() conversion. Does anyone know how that local_time variable:
int time_integer = 12345;
time_t time = (time_t)time_integer;
tm *local_time = localtime(&time);
local_time->tm_year = 100;
local_time->tm_mon = 10;
local_time->tm_mday = 1;
Convert to time_t?
Try mktime, here is its signature:
time_t mktime (struct tm * timeptr);
Returns the value of type time_t that represents the local time described by the tm structure pointed by timeptr (which may be modified).

calculate milliseconds from the mid night

I need to calculate the milliseconds from the mid night, written the code but seems there is any problem.
time_t t;
time_t rawtime;
char buff[256] ={0};
struct timeval tv;
struct timezone tz;
struct tm *tma;
gettimeofday(&tv, &tz);
tma=localtime(&tv.tv_sec);
static char* months[] = {"JAN", "FEB", "MAR", "APR", "MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
sprintf(buff,"%02d %s %d 00:00:00",tma->tm_mday, months[tma->tm_mon], tma->tm_year + 1900);
struct tm tm1;
strptime(buff, "%d %b %Y %H:%M:%S", &tm1);
tm1.tm_isdst = -1;
t = mktime(&tm1);
time ( &rawtime );
time_t milSecFromMidNight = (rawtime - t)*1000 + tv.tv_usec/1000;
It seems some time there is differences in milliseconds. Anyone can point out it?
You need to correctly calculate, as a time_t, the last previous midnight, that is, the midnight at which the current day began. You can do it something like this:
// function to calculate midnite last night
time_t // calc current day 00:00:00
today_at_0000 ( ) {
time_t curtime, midtime;
struct tm *localtm_p;
curtime = time( NULL );
localtm_p = localtime( &curtime );
localtm_p->tm_hour = 0;
localtm_p->tm_min = 0;
localtm_p->tm_sec = 0;
midtime = mktime( localtm_p ); // today at 00:00:00
return midtime;
}
The important point is you have to use mktime( ) to find midnight after setting tm_hour, tm_min, and tm_sec of the current time to zero.
You know what to do after you find the time_t of midnight.

C++ time_t problem

I'm having trouble with dates management in C++ (VS 2008).
According to MSDN specifications, time_t represents:
The number of seconds since January 1, 1970, 0:00 UTC
therefore, I've written this piece of code:
#include <stdio.h>
#include <time.h>
time_t GetDate(int year, int month, int day, int hour, int min, int sec)
{
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = gmtime ( &rawtime );
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
timeinfo->tm_hour = hour;
timeinfo->tm_min = min;
timeinfo->tm_sec = sec;
timeinfo->tm_isdst = 0; // disable daylight saving time
time_t ret = mktime ( timeinfo );
return ret;
}
int main ()
{
time_t time_0 = GetDate(1970,1,1,0,0,0);
// time_0 == -1 !!!
time_t time_1 = GetDate(1970,1,1,1,0,0);
// time_1 == 0 !!!
return 0;
}
It seems to be shifted by 1 hour (i.e. zero time is January 1, 1970, 1:00 UTC).
Initially, I thought the problem could come from the DayLightSaving flag, but it doesn't change by changing it.
Am I doing something wrong ?
Thanks in advance
P.S.
In theory, I might not mind the zero time value, because it's only a reference time.
But I need to be sure about the value, because I'm porting the code to another language and I need to get exactly the same results.
EDIT:
here's the solution, thanks to Josh Kelley Answer
time_t mktimeUTC(struct tm* timeinfo)
{
// *** enter in UTC mode
char* oldTZ = getenv("TZ");
putenv("TZ=UTC");
_tzset();
// ***
time_t ret = mktime ( timeinfo );
// *** Restore previous TZ
if(oldTZ == NULL)
{
putenv("TZ=");
}
else
{
char buff[255];
sprintf(buff,"TZ=%s",oldTZ);
putenv(buff);
}
_tzset();
// ***
return ret;
}
mktime takes a struct tm giving a local time and returns the number of seconds since January 1, 1970, 0:00 UTC. Therefore, your GetDate(1970,1,1,0,0,0); call will return 0 if your local time zone is UTC but may return other values for other time zones.
Edit: For a UTC version of mktime or your GetDate, try the following (untested):
Call getenv to save the current value of the TZ environment variable (if any).
Call putenv to change the TZ environment variable to "UTC".
Call _tzset to make your changes active.
Call mktime.
Restore the old value of TZ, then call _tzset again.
Just a WAG but try the following:
timeinfo->tm_year = year - (unsigned long)1900;
timeinfo->tm_mon = month - (unsigned long)1;