looking for another time structure with member objects other than tm - c++

the member tm_mon, in struct tm is stored as an integer. I'm looking for another time stuct that stores the actual name of the month. I can get the user-friendly format with
ctime();
but how can I selectively output just the month?

Have an array like,
string Months[] = {"January", "February", ... };
Then when you want to print use,
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
cout << Months[now-> tm_mon];

Related

C++ - Convert Given UTC Time string to Local time zone

We have string format UTC Time and we need to convert to Your Current time zone and in string format.
string strUTCTime = "2017-03-17T10:00:00Z";
Need to Convert above value to Local time in same string format.
Like in IST it would be "2017-03-17T15:30:00Z"
Got Solution...
1) Convert String formatted time to time_t
2) use "localtime_s" to Convert utc to local time.
3) use "strftime" to convert local time (struct tm format) to string format.
int main()
{
std::string strUTCTime = "2017-03-17T13:20:00Z";
std::wstring wstrUTCTime = std::wstring(strUTCTime.begin(),strUTCTime.end());
time_t utctime = getEpochTime(wstrUTCTime.c_str());
struct tm tm;
/*Convert UTC TIME To Local TIme*/
localtime_s(&tm, &utctime);
char CharLocalTimeofUTCTime[30];
strftime(CharLocalTimeofUTCTime, 30, "%Y-%m-%dT%H:%M:%SZ", &tm);
string strLocalTimeofUTCTime(CharLocalTimeofUTCTime);
std::cout << "\n\nLocal To UTC Time Conversion:::" << strLocalTimeofUTCTime;
}
std::time_t getEpochTime(const std::wstring& dateTime)
{
/* Standard UTC Format*/
static const std::wstring dateTimeFormat{ L"%Y-%m-%dT%H:%M:%SZ" };
std::wistringstream ss{ dateTime };
std::tm dt;
ss >> std::get_time(&dt, dateTimeFormat.c_str());
/* Convert the tm structure to time_t value and return Epoch. */
return _mkgmtime(&dt);
}

UTC Timestamp comparison

I'm working on a client-server custom application (to be run on linux), and one of the frames I send include a timestamp (ie the time at which the frame is send).
In order to make my application reliable, I used gmtime to produce the time on the client. I'm in Belgium, so right now the hour of the client VM is 2 hours later than the UTC time (because of the summer hour).
In the server side, I first convert the recieved string to a time_t type. I do this to use the difftime function to see if the timestamp is not too old.
Then, I generate a timestamp (in UTC time) again with gmtime, and I convert it to a time_t.
I compare then the two time_t to see the time difference.
I have got a problem with the conversion of the time at the server side. I use the same code as in the client, but the outputted gmtime is different...
Client Side : function to generate the timestamp, and export it to a string (time_str):
std::string getTime()
{
time_t rawtime;
struct tm * timeinfo;
char buffer[80];
time (&rawtime); // Get time of the system
timeinfo = gmtime(&rawtime); // Convert it to UTC time
strftime(buffer,80,"%d-%m-%Y %H:%M:%S",timeinfo);
std::string time_str(buffer); // Cast it into a string
cout<<"Time Stamp now (client) : "<<time_str<<endl;
return time_str;
}
And it produices this (at 9h33 local time) :
Time Stamp now : 06-04-2016 07:33:30
Server Side : fucntion to retrieve the timestamp, generate the newx time stamp, and compare them :
bool checkTimeStamp(std::string TimsStamp_str, double delay)
{
cout<<"TimeStamp recieved: "<<TimsStamp_str<<endl;
/* Construct tm from string */
struct tm TimeStampRecu;
strptime(TimsStamp_str.c_str(), "%d-%m-%Y %I:%M:%S", &TimeStampRecu);
time_t t_old = mktime(&TimeStampRecu);
/* Generate New TimeStamp */
time_t rawtime;
struct tm * timeinfo;
time (&rawtime); // Get time of the system
timeinfo = gmtime(&rawtime); // convert it to UTC time_t
time_t t2 = mktime(timeinfo); // Re-Cast it to timt_t struct
/* Convert it into string (for output) */
char buffer[80];
strftime(buffer,80,"%d-%m-%Y %H:%M:%S",timeinfo);
std::string time_str(buffer); // Cast it into a string
cout<<"Time Stamp now (server) : "<<time_str<<endl;
/* Comparison */
double diffSecs = difftime(t2, t_old);
cout<<diffSecs<<endl;
bool isTimeStampOK;
if (diffSecs < delay)
isTimeStampOK = true;
else
isTimeStampOK = false;
return isTimeStampOK;
}
And it produces this (at 9h33 in Belgium) :
TimeStamp recieved : 06-04-2016 07:33:30
Time Stamp now (server) : 06-04-2016 08:33:31
Why is the Server Time (8h33) neither in localtime (9h33), neither in UTC time (7h33) ?
Have I made a mistake in its generation ? I don't understand where, because these are the exact same code as in the client side...
There's a couple of errors in your code, some your fault, some not. The biggest problem here is that the C <time.h> API is so poor, confusing, incomplete and error prone that errors like this are very nearly mandatory. More on that later.
The first problem is this line:
struct tm TimeStampRecu;
It creates an uninitialized tm and then passes that into strptime. strptime may not fill in all the fields of TimeStampRecu. You should zero-initialize TimeStampRecu like this:
struct tm TimeStampRecu{};
Next problem:
strptime(TimsStamp_str.c_str(), "%d-%m-%Y %I:%M:%S", &TimeStampRecu);
The 12-hour time denoted by %I is ambiguous without an AM/PM specifier. I suspect this is just a type-o as it is the only place you use it.
Next problem:
gmtime time_t -> tm UTC to UTC
mktime tm -> time_t local to UTC
That is, mtkime interprets the input tm according to the local time of the computer it is running on. What you need instead is:
timegm tm -> time_t UTC to UTC
Unfortunately timegm isn't standard C (or C++). Fortunately it probably exists anyway on your system.
With these changes, I think your code will run as expected.
If you are using C++11, there is a safer date/time library to do this here (free/open-source):
https://github.com/HowardHinnant/date
Here is your code translated to use this higher-level library:
std::string getTime()
{
using namespace std::chrono;
auto rawtime = time_point_cast<seconds>(system_clock::now());
auto time_str = date::format("%d-%m-%Y %H:%M:%S", rawTime);
std::cout<<"Time Stamp now (client) : "<<time_str<< '\n';
return time_str;
}
bool checkTimeStamp(std::string TimsStamp_str, std::chrono::seconds delay)
{
using namespace std::chrono;
std::cout<<"TimeStamp recieved: "<<TimsStamp_str<< '\n';
/* Construct tm from string */
std::istringstream in{TimsStamp_str};
time_point<system_clock, seconds> t_old;
date::parse(in, "%d-%m-%Y %H:%M:%S", t_old);
/* Generate New TimeStamp */
auto rawtime = time_point_cast<seconds>(system_clock::now());
auto time_str = date::format("%d-%m-%Y %H:%M:%S", rawTime);
in.str(time_str);
time_point<system_clock, seconds> t2;
date::parse(in, "%d-%m-%Y %H:%M:%S", t2);
cout<<"Time Stamp now (server) : "<<time_str<<endl;
/* Comparison */
auto diffSecs = t2 - t_old;
cout<<diffSecs.count()<<endl;
bool isTimeStampOK;
if (diffSecs < delay)
isTimeStampOK = true;
else
isTimeStampOK = false;
return isTimeStampOK;
}
A timestamp is an absolute value. It doesn't depend on timezones or DST. It represents the number of seconds since a fixed moment in the past. The value returned by time() is the same, no matter what the timezone of the server is.
Your code doesn't produce timestamps but dates formatted for human consumption.
I recommend you use timestamps internally and format them to dates readable by humans only in the UI. However, if you need to pass dates as strings between various components of your application, also put the timezone in them.
I would write your code like this (using only timestamps):
// The client side
time_t getTime()
{
return time(NULL);
}
// The server side
bool checkTimeStamp(time_t clientTime, double delay)
{
time_t now = time(NULL);
return difftime(now, clientTime) < delay;
}
Update
If you have to use strings to communicate between client and server then all you have to do is to update the format string used to format the timestamps as dates (on the client) and parse the dates back to timestamps (on the server), to include the timezone you used to format the date.
This means add %Z into the format everywhere in your code. Use "%d-%m-%Y %H:%M:%S %Z". Btw, the code you posted now reads "%d-%m-%Y %I:%M:%S" in the call to strptime() and that will bring you another problem in the afternoon.
Remark
I always use "%Y-%m-%d %H:%M:%S %Z" because it is unambiguous and locale-independent. 06-04-2016 can be interpreted as April 6 or June 4, depending of the native language of the reader.

How to add 1 hour to 8601 format time string in C++ on Windows?

I've got an 8601 format time string like so:
std::string strTime("1601-01-01T00:01:53.537Z");
I want to increment the hour and change its value to
"1601-01-01T01:01:53.537Z"
I think the steps are: convert string to a time object, increment the hour by 1, convert the object back to a string.
Of course, it would be helpful if all the normal time considerations and boundaries were taken into account (such as adding an hour to 11:30 pm will move to the next day, etc...). I've been looking at strftime, strptime, std::get_time and others but have not been able to work it out yet.
I'm using VS2012 on Windows. Thanks.
Some pseudo code to get you started.
char *AddHour(char *dest, size_t size, const char *timestamp) {
Initialize struct tm
Scan timestamp into tm
Check scanning success
Check year range validity
Bring into range acceptable by mktime()
Add hour
Call mktime()
Undo range adjustment made beforehand
Print tm to dest
return dest;
}
Even though mktime() uses local timezone, by keeping the tm_isdst == 0 we can use this for the Z timezone (UTC) for all practical purposes.
Simply scan the string into various parts. Add 1 hour and then reform the string
string --> struct tm tm;
// Add hour
if (++tm.tm_hour >= 24) {
tm.tm_hour = 0;
if (++tm.tm_mday > EOM(tm.tm_year, tm.tm_mon)) {
tm.tm_mday = 1;
if (++tm.tm_mon > 12) {
tm.tm_mon = 1;
tm.tm_year++;
}
}
}
struct tm tm --> string
I have written a C library that parses and formats a ISO 8601 calendar date with time and zone designator in extended format. It's available on Github, c-timestamp.
{
timestamp_t ts;
char *str = "1601-01-01T00:01:53.537Z";
timestamp_parse(str, strlen(str), &ts);
ts.sec += 1*60*60;
timestamp_format(str, strlen(str), &ts);
puts(str);
}

C++ mktime returning random dates

I'm trying to convert a date string to a time_t, but mktime() is returning seemingly random dates:
string datetime = "2014-12-10 10:30";
struct tm tmInfo;
strptime(datetime.c_str(), "%Y-%m-%d %H:%M", &tmInfo);
tmInfo.tm_isdst = 0;
time_t eventTime = mktime(&tmInfo);
eventTime ranges wildly from the 1970s to the 2030s. The tmInfo struct holds the correct date, so the error must be happening in mktime(). Any ideas of what's going wrong?
You need to properly zero-initialize all of the other fields of the struct tm instance before calling strptime(), since it doesn't necessarily initialize every field. From the strptime() POSIX specification:
It is unspecified whether multiple calls to strptime() using the same tm structure will update the current contents of the structure or overwrite all contents of the structure. Conforming applications should make a single call to strptime() with a format and all data needed to completely specify the date and time being converted.
For example, this should suffice:
struct tm tmInfo = {0};
You have to initialize the struct to 0 beforehand or also input the seconds:
string datetime = "2014-12-10 10:30";
struct tm tmInfo = { 0 };
strptime(datetime.c_str(), "%Y-%m-%d %H:%M", &tmInfo);
or
string datetime = "2014-12-10 10:30:00";
struct tm tmInfo;
strptime(datetime.c_str(), "%Y-%m-%d %H:%M:%S", &tmInfo);
The below code would do the work, if you want current system time in an format
time_t current_time;
struct tm *loctime;
memset(buffer,0,strlen(buffer));
current_time = time(NULL);
loctime = localtime(&current_time);
strftime(buffer,250,"--> %d/%m/%y %H:%M:%S",loctime);

simple c++ time program error

I am messing around with the time header and have encountered an error:
invalid conversion from 'tm*' to 'time_t'
You can see the where the error is in the code below all the way at the bottom when I try to use the difftime function. I know im just doing something stupid and illegal but I cant see how I can get around this. If anyone has a solution let me know. Thanks!
The program is supposed to get the current time, take time input from a user, and then find the time difference.
Code:
#include <stdio.h>
#include <time.h>
int main ()
{
time_t rawtime;
struct tm * timeinfo;
struct tm * cur_timeinfo_hold;
int year, month ,day,hour,minute,second;
double dif;
/* prompt user for time to be compared*/
printf ("Enter year: "); scanf ("%d",&year);
printf ("Enter month: "); scanf ("%d",&month);
printf ("Enter day: "); scanf ("%d",&day);
printf ("Enter hour: "); scanf ("%d",&hour);
printf ("Enter minute: "); scanf ("%d",&minute);
printf ("Enter second: "); scanf ("%d",&second);
/* get current timeinfo*/
time ( &rawtime );
timeinfo = localtime ( &rawtime );
/* print it */
printf("The present time is: "); printf(asctime (timeinfo));
/* set current time into a new variable to use for difftime, since timeinfo, will be changed */
cur_timeinfo_hold = timeinfo;
/* modify current timeinfo to the user's choice */
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
timeinfo->tm_hour = hour;
timeinfo->tm_min = minute;
timeinfo->tm_sec = second;
mktime ( timeinfo );
/* and print it */
printf ("time to compare: "); printf(asctime (timeinfo));
/* find time difference */
//dif = difftime (cur_timeinfo_hold,timeinfo); //error: invalid conversion from 'tm*' to 'time_t'
return 0;
}
mktime is a function. It accepts one parameter, a tm pointer, and returns a value, a time_t. It does not transform its argument from one type into another. Therefore, after you call mktime(timeinfo), your timeinfo variable is still a tm pointer.
The difftime function expects to receive two time_t values, so it won't accept cur_timeinfo_hold or timeinfo; they're the wrong type. The first variable's value came from converting rawtime to a tm pointer with localtime, so use that for the first parameter. When you later called mktime(timeinfo), it returned a time_t value, but you ignored the return value. Assign the return value to a variable so you can use it for the second difftime parameter.
time_t info = mktime(timeinfo);
// ...
dif = difftime(rawtime, info);
It's because difftime requires the raw time_t values, not the struct tm structures.
The prototype is:
double difftime(time_t time1, time_t time0);
What you'll need to do is leave the system time as it is (no localtime performed on it) and then properly convert your user-entered information into the equivalent time_t with mktime (or timegm if working with UTC times).
Then you can use difftime to get the difference. Effectively, something like:
time_t base, other;
struct tm tms;
double delta;
time (&base); // basetime is now.
tms.blah = blah; // for all blahs.
other = mktime (&tms); // get time_t for other time.
delta = difftime (other, base); // get difference.