diff --git a/docs/changes.txt b/docs/changes.txt index d29c67521d..c6f93d8848 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -711,6 +711,7 @@ wxMSW: - Fix filter checks in wxDir::FindFirst/Next() (Catalin Raceanu). - Add support for wxICON_AUTH_NEEDED to wxMessageDialog (Chris Spencer). - Fix printing too many copies of the document in some cases (John Roberts). +- Fix DST confusion in wxFileName::{Set,Get}Times(). wxOSX/Cocoa: diff --git a/src/common/filename.cpp b/src/common/filename.cpp index d6d68aeeb6..44b47f0719 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -93,6 +93,7 @@ #include "wx/config.h" // for wxExpandEnvVars #include "wx/dynlib.h" #include "wx/dir.h" +#include "wx/longlong.h" #if defined(__WIN32__) && defined(__MINGW32__) #include "wx/msw/gccpriv.h" @@ -231,49 +232,30 @@ private: #if wxUSE_DATETIME && defined(__WIN32__) && !defined(__WXMICROWIN__) -// convert between wxDateTime and FILETIME which is a 64-bit value representing -// the number of 100-nanosecond intervals since January 1, 1601. +// Convert between wxDateTime and FILETIME which is a 64-bit value representing +// the number of 100-nanosecond intervals since January 1, 1601 UTC. +// +// This is the offset between FILETIME epoch and the Unix/wxDateTime Epoch. +static wxInt64 EPOCH_OFFSET_IN_MSEC = wxLL(11644473600000); static void ConvertFileTimeToWx(wxDateTime *dt, const FILETIME &ft) { - FILETIME ftcopy = ft; - FILETIME ftLocal; - if ( !::FileTimeToLocalFileTime(&ftcopy, &ftLocal) ) - { - wxLogLastError(wxT("FileTimeToLocalFileTime")); - } + wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime); + t /= 10000; // Convert hundreds of nanoseconds to milliseconds. + t -= EPOCH_OFFSET_IN_MSEC; - SYSTEMTIME st; - if ( !::FileTimeToSystemTime(&ftLocal, &st) ) - { - wxLogLastError(wxT("FileTimeToSystemTime")); - } - - dt->Set(st.wDay, wxDateTime::Month(st.wMonth - 1), st.wYear, - st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); + *dt = wxDateTime(t); } static void ConvertWxToFileTime(FILETIME *ft, const wxDateTime& dt) { - SYSTEMTIME st; - st.wDay = dt.GetDay(); - st.wMonth = (WORD)(dt.GetMonth() + 1); - st.wYear = (WORD)dt.GetYear(); - st.wHour = dt.GetHour(); - st.wMinute = dt.GetMinute(); - st.wSecond = dt.GetSecond(); - st.wMilliseconds = dt.GetMillisecond(); + // Undo the conversions above. + wxLongLong t(dt.GetValue()); + t += EPOCH_OFFSET_IN_MSEC; + t *= 10000; - FILETIME ftLocal; - if ( !::SystemTimeToFileTime(&st, &ftLocal) ) - { - wxLogLastError(wxT("SystemTimeToFileTime")); - } - - if ( !::LocalFileTimeToFileTime(&ftLocal, ft) ) - { - wxLogLastError(wxT("LocalFileTimeToFileTime")); - } + ft->dwHighDateTime = t.GetHi(); + ft->dwLowDateTime = t.GetLo(); } #endif // wxUSE_DATETIME && __WIN32__ diff --git a/tests/filename/filenametest.cpp b/tests/filename/filenametest.cpp index 10ef920f39..3117760f13 100644 --- a/tests/filename/filenametest.cpp +++ b/tests/filename/filenametest.cpp @@ -35,6 +35,7 @@ #endif // __UNIX__ #include "testfile.h" +#include "testdate.h" // ---------------------------------------------------------------------------- // test data @@ -139,6 +140,7 @@ private: CPPUNIT_TEST( TestVolumeUniqueName ); CPPUNIT_TEST( TestCreateTempFileName ); CPPUNIT_TEST( TestGetTimes ); + CPPUNIT_TEST( TestSetTimes ); CPPUNIT_TEST( TestExists ); CPPUNIT_TEST( TestIsSame ); #if defined(__UNIX__) @@ -161,6 +163,7 @@ private: void TestVolumeUniqueName(); void TestCreateTempFileName(); void TestGetTimes(); + void TestSetTimes(); void TestExists(); void TestIsSame(); #if defined(__UNIX__) @@ -664,6 +667,27 @@ void FileNameTestCase::TestGetTimes() CPPUNIT_ASSERT(dtAccess.IsEqualUpTo(wxDateTime::Now(), wxTimeSpan(0,1))); } +void FileNameTestCase::TestSetTimes() +{ + wxFileName fn(wxFileName::CreateTempFileName("filenametest")); + CPPUNIT_ASSERT( fn.IsOk() ); + wxON_BLOCK_EXIT1( wxRemoveFile, fn.GetFullPath() ); + + const wxDateTime dtAccess(1, wxDateTime::Jan, 2013); + const wxDateTime dtModify(1, wxDateTime::Feb, 2013); + const wxDateTime dtCreate(1, wxDateTime::Mar, 2013); + + CPPUNIT_ASSERT( fn.SetTimes(&dtAccess, &dtModify, &dtCreate) ); + + wxDateTime dtAccess2, + dtModify2, + dtCreate2; + CPPUNIT_ASSERT( fn.GetTimes(&dtAccess2, &dtModify2, &dtCreate2) ); + CPPUNIT_ASSERT_EQUAL( dtAccess, dtAccess2 ); + CPPUNIT_ASSERT_EQUAL( dtModify, dtModify2 ); + CPPUNIT_ASSERT_EQUAL( dtCreate, dtCreate2 ); +} + void FileNameTestCase::TestExists() { wxFileName fn(wxFileName::CreateTempFileName("filenametest"));