2016-10-24 18 views
1

WindowsはDATEタイプを使用して日付を表します。これは、1899年12月30日(深夜)からの日数を表すdouble値です。Windows DATEをC++でUNIX時刻に変換する方法

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> 
+1

違いは(明らかに)固定秒数なので、適切な定数を加算または減算してみてください。それが 'DATE'値の特殊性のために動作しない場合は、単に"日数 "よりも厳密な定義が必要です。たぶんあなたはWindowsに 'DATE'を扱いやすいものに変換するように頼むことができます。ファイル時間? –

+1

@ Cheersandhth.-Alf残念なことに、はい、「DATE」は[本当に毛深い]です(https://blogs.msdn.microsoft.com/ericlippert/2003/09/16/erics-complete-guide-to-vt_date/)。 – andlabs

+0

@andlabsおそらく、単純な数学の変換はUTC時間には有効ですが、精度のために数秒遅れることがあります。この記事では、OSが扱うべきテキスト形式とDST /ローカル時間について述べています。 –

答えて

1

使用VariantTimeToSystemTimeSYSTEMTIMEDATEを変換します。

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_epoch

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 

代替方法として計算、116444736000000000Uです

+0

[FILETIMEを使用すると、 'struct tm'を使用する必要がなくなるため、エラーが発生しにくくなります。](https://blogs.msdn.microsoft.com/oldnewthing/20030905-02/?p=42653)([Mind (https://blogs.msdn.microsoft.com/oldnewthing/20131101-00/?p=2763)[タイムゾーン](https://blogs.msdn.microsoft.com/oldnewthing/20140307-00/) ?p = 1573)) – andlabs

+0

@andlabs良いアイデア、それを変更しました –

関連する問題