C convert char[] to timestamp; - c++

I have char date[] = "2011-04-01"; How it convert to timestamp in C or C++ ?

Warning: strptime is a POSIX-function (may not be available through time.h on OS "Windows" platform).
#include <time.h>
struct tm time;
strptime("2011-04-01", "%Y-%m-%d", &time);
time_t loctime = mktime(&time); // timestamp in current timezone
time_t gmttime = timegm(&time); // timestamp in GMT

Try this:
char date[] = "2011-04-01";
date[4] = date[7] = '\0';
struct tm tmdate = {0};
tmdate.tm_year = atoi(&date[0]) - 1900;
tmdate.tm_mon = atoi(&date[5]) - 1;
tmdate.tm_mday = atoi(&date[8]);
time_t t = mktime( &tmdate );

Related

Calculate the daily midnight time from current timestamp

Like suppose Current time is 2021-05-16 22:42 then midnight time be 2021-05-17 00:00:00 at 12 when time change.
I want to calculate the time left in midnight to come from the current time.
You could do:
#include <iostream>
#include <ctime>
#include <sstream>
int main() {
struct tm tm;
std::string s("2013-12-04 15:03");
strptime(s.c_str(), "%Y-%m-%d %H:%M", &tm);
struct tm tm1 = tm;
tm1.tm_mday = tm1.tm_mday +1;
tm1.tm_hour = 0;
tm1.tm_min = 0;
double secs = std::difftime(mktime(&tm1), mktime(&tm));
std::cout<<secs<<" seconds\n";
return 0;
}

Converting Char array to TimeStamp in C++

I have char start_time[40] = "2020-04-01 12:00:00"; How can I convert the char array to timestamp in C++ without using strptime?
You can try this:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main(void) {
const char T[] = "2020-04-01 12:00:00";
time_t result = 0;
int year = 0, month = 0, day = 0, hour = 0, min = 0,sec=0;
if (sscanf(T, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min,&sec) == 6) {
struct tm test_time = {0};
test_time.tm_year = year - 1900; /* years since 1900 */
test_time.tm_mon = month - 1;
test_time.tm_mday = day;
test_time.tm_hour = hour;
test_time.tm_min = min;
test_time.tm_sec = sec;
if ((result = mktime(&test_time)) == (time_t)-1) {
fprintf(stderr, "Cannot convert time to time_t\n");
return EXIT_FAILURE;
}
std::cout << result << '\n' ;
puts(ctime(&result));
struct tm *t_start = localtime(&result);
char date_time[30];
strftime( date_time, sizeof(date_time), "%Y-%m-%d %H:%M:%S", t_start );
std::cout << date_time << '\n' ;
return EXIT_SUCCESS;
}
else {
fprintf(stderr, "The input was not a valid time format\n");
return EXIT_FAILURE;
}
}

How can a Windows DATE be converted into a Unix time in c++

Windows uses the DATE type to represent dates. This is a double value representing the number of days since 30 December 1899, midnight.
How can a DATE be converted into a Unix timestamp (the number of seconds since 01 January 1970) value?
Specifically, how can this be achieved using only the c++ standard library, and windows libraries for which MinGW distributes header files?
For example, I can get a date property from an IShellFolder2:
void MyFunc(IShellFolder2 *folder, PCUITEMID_CHILD pidl, const SHCOLUMNID *columnid) {
VARIANT* v = (VARIANT*) malloc(sizeof(VARIANT));
DATE d;
HRESULT hr = folder->GetDetailsEx(pidl, colid, v);
if (SUCCEEDED(hr)) {
hr = VariantChangeType(v, v, 0, VT_DATE);
if (SUCCEEDED(hr)) {
d = v->date;
}
VariantClear(v);
}
free(v);
// process date here
}
How do I then transform this value for use with software that uses the Unix timestamp format?
Currently used header files (not all relevant to this specific issue):
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <propkey.h>
#include <wchar.h>
#include <shlguid.h>
#include <string>
#include <vector>
Use VariantTimeToSystemTime to convert DATE to SYSTEMTIME.
Conversion of SYSTEMTIME to unix time is then a simple task.
In Visual Studio you could use COleDateTime but that's not available in MinGW
#include <Windows.h>
#include <stdio.h>
#include <time.h>
#include <OleAuto.h>
unsigned int unix_stamp_of_DATE(DATE date)
{
//convert DATE to SYSTEMTIME
SYSTEMTIME st;
VariantTimeToSystemTime(date, &st);
//convert SYSTEMTIME to FILETIME
FILETIME ft;
SystemTimeToFileTime(&st, &ft);
//convert FILETIME to ULARGE_INTEGER
//then QuadPart is 64bit timestamp
ULARGE_INTEGER ul{ ft.dwLowDateTime, ft.dwHighDateTime };
return (unsigned int)((ul.QuadPart - 116444736000000000ULL)/10000000);
}
Usage:
int main()
{
DATE dt = 25569.000000f; //1970, 1, 1
time_t rawtime = unix_stamp_of_DATE(dt);
tm *timeinfo = gmtime(&rawtime); //DATE was UTC!
char buf[50];
strftime(buf, sizeof(buf), "%c", timeinfo);
printf("%s\n", buf);
return 0;
}
Explanation: unix_epoch is 116444736000000000U, calculated as
ULARGE_INTEGER unix_epoch{ 0 };
FILETIME ft;
SYSTEMTIME st = { 0 };
st.wDay = 1;
st.wMonth = 1;
st.wYear = 1970;
SystemTimeToFileTime(&st, &ft);
unix_epoch = ULARGE_INTEGER{ ft.dwLowDateTime, ft.dwHighDateTime };
//=116444736000000000U
Alternate method
int main()
{
DATE dt = 25569.000000; //1970,1,1
SYSTEMTIME st;
VariantTimeToSystemTime(dt, &st);
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
//system time or localtime?
timeinfo = gmtime(&rawtime);
//timeinfo = localtime(&rawtime);
timeinfo->tm_year = st.wYear - 1900;
timeinfo->tm_mon = st.wMonth - 1;
timeinfo->tm_mday = st.wDay;
timeinfo->tm_hour = st.wHour;
timeinfo->tm_min = st.wMinute;
timeinfo->tm_sec = st.wSecond;
mktime(timeinfo);
printf("%d\n", st.wYear);
return 0;
}

Get a time_t from universal time string?

If I have this string:
2011-10-08T07:07:09Z
is it possible to get a time_t from it? If so, how can this be done?
Yes, it is. First, convert it to a broken down time with strptime(3). This gives you a struct tm, which is the structure type for a broken down time.
From there, you can convert to a time_t with mktime(3).
Here's an example:
#define _XOPEN_SOURCE
#include <time.h>
#include <stdio.h>
#include <string.h>
int main(void) {
const char *date_example = "2011-10-08T07:07:09Z";
struct tm broken_down;
memset(&broken_down, 0, sizeof(broken_down));
strptime(date_example, "%Y-%m-%dT%H:%M:%SZ", &broken_down);
broken_down.tm_isdst = 0; // Indicates that DST is not in effect
time_t epoch_time = mktime(&broken_down);
// Note: this is platform dependent
printf("Epoch time: %lld\n", (long long) epoch_time);
return 0;
}
Use sscanf() to tear apart the time. The trick is somehow determine the difference between local and universal time so code may call mktime() - which uses assumes struct tm is local time..
#include <time.h>
#include <stdio.h>
int Get_TZ_delta(const struct tm *tmptr) {
// Make local copy
struct tm tm = *tmptr;
time_t t = mktime(&tm);
struct tm utc_tm = *gmtime(&t);
time_t t2 = mktime(&utc_tm);
return (int) difftime(t, t2);
}
time_t UniversalTimeStamp_to_time_t(const char *ts) {
struct tm tm = { 0 };
// Use a sentinel to catch extra garbage
char sentinel;
if (sscanf(ts, "%d-%2d-%2dT%2d:%2d:%2dZ%c", &tm.tm_year, &tm.tm_mon,
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &sentinel) != 6) {
return -1;
}
// struct tm uses offset from 1900 and January is month 0
tm.tm_year -= 1900;
tm.tm_mon--;
// Convert tm from UCT to local standard time
tm.tm_isdst = 0;
tm.tm_sec += Get_TZ_delta(&tm);
time_t t = mktime(&tm); // mktime() assumes tm is local
// test code
{
printf("UTC `%s`\n", ts);
char buf[100];
strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S %Z", &tm);
printf("Local %s\n", buf);
printf("Unix %lld\n\n", (long long) mktime(&tm));
}
return t;
}
int main(void) {
UniversalTimeStamp_to_time_t("2015-06-18T22:07:52Z");
UniversalTimeStamp_to_time_t("2011-10-08T07:07:09Z");
UniversalTimeStamp_to_time_t("1970-01-01T00:00:00Z");
return 0;
}
Output
UTC `2015-06-18T22:07:52Z`
Local 2015-06-18T17:07:52 CDT
Unix 1434665272
UTC `2011-10-08T07:07:09Z`
Local 2011-10-08T02:07:09 CDT
Unix 1318057629
UTC `1970-01-01T00:00:00Z`
Local 1969-12-31T18:00:00 CST
Unix 0
Another approach works should code know that time_t is the number of seconds since Jan 1, 1970 0:00:00. Uses sscanf() to parse the string, calculate the number of days, and then return the number of seconds.
#include <time.h>
#include <stdio.h>
#define MARCH 3
#define DaysPer400Years (400*365LL + 97)
#define DaysPer100Years (100*365LL + 24)
#define DaysPer4Years (4*365LL + 1)
#define DaysPer1Year 365LL
#define DayNumber1970Jan1 719469LL
long long DayNumber(int year, int Month, int Day, long epoch) {
long long dn = Day;
long long y = year;
y += Month / 12;
Month %= 12;
while (Month < MARCH) {
Month += 12;
y--;
}
// And then a miracle occurs.
dn += ((Month - MARCH) * (7832 / 4) + (140 / 4)) >> (8 - 2);
dn += (y / 400) * DaysPer400Years;
y %= 400;
dn += (y / 100) * DaysPer100Years;
y %= 100;
dn += (y / 4) * DaysPer4Years;
y %= 4;
dn += y * DaysPer1Year;
return dn - epoch;
}
time_t UniversalTimeStamp_to_time_t(const char *ts) {
int y,m,d,H,M,S;
// Use a sentinel to catch extra garbage
char sentinel;
if (sscanf(ts, "%d-%2d-%2dT%2d:%2d:%2dZ%c", &y, &m,
&d, &H, &M, &S, &sentinel) != 6) {
return -1;
}
long long t = DayNumber(y, m, d, DayNumber1970Jan1);
t = t*24L*60*60 + 3600L*H + 60*M + S;
// test code
{
printf("UTC `%s`\n", ts);
time_t tt = t;
struct tm tm = *gmtime(&tt);
char buf[100];
strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S %Z", &tm);
printf("Local %s\n", buf);
printf("Unix %lld\n\n", t);
}
return t;
}
int main(void) {
UniversalTimeStamp_to_time_t("2015-06-18T22:07:52Z");
UniversalTimeStamp_to_time_t("2011-10-08T07:07:09Z");
UniversalTimeStamp_to_time_t("1970-01-01T00:00:00Z");
return 0;
}
Output
UTC `2015-06-18T22:07:52Z`
Local 2015-06-18T22:07:52
Unix 1434665272
UTC `2011-10-08T07:07:09Z`
Local 2011-10-08T07:07:09
Unix 1318057629
UTC `1970-01-01T00:00:00Z`
Local 1970-01-01T00:00:00
Unix 0

How to convert a string variable containing time to time_t type in c++?

I have a string variable containing time in hh:mm:ss format. How to convert it into time_t type? eg: string time_details = "16:35:12"
Also, how to compare two variables containing time so as to decide which is the earliest?
eg : string curr_time = "18:35:21"
string user_time = "22:45:31"
With C++11 you can now do
struct std::tm tm;
std::istringstream ss("16:35:12");
ss >> std::get_time(&tm, "%H:%M:%S"); // or just %T in this case
std::time_t time = mktime(&tm);
see std::get_time and strftime for reference
You can use strptime(3) to parse the time, and then mktime(3) to convert it to a time_t:
const char *time_details = "16:35:12";
struct tm tm;
strptime(time_details, "%H:%M:%S", &tm);
time_t t = mktime(&tm); // t is now your desired time_t
This should work:
int hh, mm, ss;
struct tm when = {0};
sscanf_s(date, "%d:%d:%d", &hh, &mm, &ss);
when.tm_hour = hh;
when.tm_min = mm;
when.tm_sec = ss;
time_t converted;
converted = mktime(&when);
Modify as needed.
Here's the complete C implementation with date & time.
enum DateTimeFormat {
YearMonthDayDash, // "YYYY-MM-DD hh:mm::ss"
MonthDayYearDash, // "MM-DD-YYYY hh:mm::ss"
DayMonthYearDash // "DD-MM-YYYY hh:mm::ss"
};
//Uses specific datetime format and returns the Linux epoch time.
//Returns 0 on error
static time_t ParseUnixTimeFromDateTimeString(const std::wstring& date, DateTimeFormat dateTimeFormat)
{
int YY, MM, DD, hh, mm, ss;
struct tm when = { 0 };
int res;
if (dateTimeFormat == DateTimeFormat::YearMonthDayDash) {
res = swscanf_s(date.c_str(), L"%d-%d-%d %d:%d:%d", &YY, &MM, &DD, &hh, &mm, &ss);
}
else if (dateTimeFormat == DateTimeFormat::MonthDayYearDash) {
res = swscanf_s(date.c_str(), L"%d-%d-%d %d:%d:%d", &MM, &DD, &YY, &hh, &mm, &ss);
}
else if (dateTimeFormat == DateTimeFormat::DayMonthYearDash) {
res = swscanf_s(date.c_str(), L"%d-%d-%d %d:%d:%d", &DD, &MM, &YY, &hh, &mm, &ss);
}
//In case datetime was in bad format, returns 0.
if (res == EOF || res == 0) {
return 0;
}
when.tm_year = YY - 1900; //Years from 1900
when.tm_mon = MM - 1; //0-based
when.tm_mday = DD; //1 based
when.tm_hour = hh;
when.tm_min = mm;
when.tm_sec = ss;
//Make sure the daylight savings is same as current timezone.
time_t now = time(0);
when.tm_isdst = std::localtime(&now)->tm_isdst;
//Convert the tm struct to the Linux epoch
time_t converted;
converted = mktime(&when);
return converted;
}
use strptime.
struct tm tm;
memset(&tm, 0, sizeof(tm));
char *res = strptime(strtime.c_str(), format.c_str(), &tm);
if (res == nullptr) {
// err process
}
ti = mktime(&tm);
Must init tm, and check the return value.