Reputation: 947
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>
Upvotes: 1
Views: 3015
Reputation: 31639
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;
}
Upvotes: 0