【问题标题】:How can a Windows DATE be converted into a Unix time in c++如何在 C++ 中将 Windows DATE 转换为 Unix 时间
【发布时间】:2017-03-05 18:41:03
【问题描述】:

Windows 使用DATE 类型来表示日期。这是一个double 值,表示自 1899 年 12 月 30 日午夜以来的天数。

如何将DATE 转换为 Unix 时间戳(自 1970 年 1 月 1 日以来的秒数)值?

具体来说,如何仅使用 c++ 标准库和 MinGW 为其分发头文件的 windows 库来实现?

例如,我可以从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
}

然后如何转换此值以用于使用 Unix 时间戳格式的软件?

当前使用的头文件(并非都与此特定问题相关):

#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>

【问题讨论】:

  • 由于差异(显然)是固定的秒数,因此可以尝试添加或减去一个合适的常数。如果由于 DATE 值的特殊性而这不起作用,那么您需要一个比“天数”更严格的定义。也许您可以要求 Windows 将 DATE 转换为更容易处理的东西,例如文件时间?
  • @Cheersandhth.-Alf 不幸的是,DATEreally hairy
  • @andlabs 可能一个简单的数学转换适用于 UTC 时间,但由于精度可能会相差几秒钟。那篇文章讨论了操作系统应该处理的文本格式和 DST/本地时间。

标签: c++ date winapi com unix-timestamp


【解决方案1】:

使用VariantTimeToSystemTimeDATE 转换为SYSTEMTIME

SYSTEMTIME 到 unix 时间的转换是一项简单的任务。

在 Visual Studio 中,您可以使用 COleDateTime,但这在 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);
}

用法:

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;
}

说明:unix_epoch116444736000000000U,计算为

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

替代方法

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;
}
猜你喜欢
  • 2014-12-10
  • 2014-04-07
  • 2016-04-03
  • 2016-07-12
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 2013-12-20
  • 2016-01-20
相关资源
最近更新 更多