Benutzer mit den meisten Antworten
Dateidatum in VC++ 2008 und 2010

Frage
-
Hallo,
Ich habe heute eine für mich momentan recht problematische Entdeckung bezüglich _findfirst() und Zeitstempel gemacht. Kurz zusammengefaßt ist der von VC++ 2010 gelieferte Zeitstempel eine Stunde in der Zukunft während VC++ 2008 den richtigen Zeitstempel liefert.
Ausprobiert:
- Zeitzonenänderung hat keine Wirkung
- "Uhr automatisch auf Sommer-/Winterzeit umstellen" deaktiviert tritt das Problem nicht auf
- Dateisystem (FAT / NTFS) macht keinen Unterschied
Hier ist mein Testprogramm:
#include <io.h> #include <time.h> #include <string.h> #include <iostream> #include <fstream> #include <string>
std::string time2str(time_t t) { char buffer[128]; struct tm localTimeStruct; localtime_s(&localTimeStruct, &t); sprintf_s(buffer, sizeof(buffer), "%02d:%02d:%02d", localTimeStruct.tm_hour, localTimeStruct.tm_min, localTimeStruct.tm_sec); return buffer; } int main(int argc, char **argv) { static const char *filename = "d:\\test.txt"; // update write timestamp { std::ofstream stream(filename); stream.close(); } // current status time_t now = time(NULL); std::cout << "_MSC_VER: " << _MSC_VER << std::endl << "Now: " << time2str(now) << " (" << now << ")" << std::endl << " _daylight=" << _daylight << std::endl << " _dstbias=" << _dstbias << std::endl << " _timezone=" << _timezone << std::endl; // query file and print timestamps _finddata_t fd; intptr_t fh = _findfirst( filename, &fd); if (fh != -1) { struct tm C, M, A; localtime_s(&C, &fd.time_create); localtime_s(&M, &fd.time_write); localtime_s(&A, &fd.time_access); std::cout << fd.name << ": " << fd.size << std::endl << " Create: " << time2str(fd.time_create) << " (" << fd.time_create << ")" << std::endl << " Write: " << time2str(fd.time_write) << " (" << fd.time_write << ")" << std::endl << " Access: " << time2str(fd.time_access) << " (" << fd.time_access << ")" << std::endl; _findclose(fh); } return 0; }Die folgenden Tests habe ich mit GMT+1 und automatischer Sommerzeit gemacht.
Ergebniss in 2008 stimmt mit Windows Explorer Anzeige überein:
_MSC_VER: 1500
Now: 14:02:34 (1306756954)
_daylight=1
_dstbias=-3600
_timezone=28800
test.txt: 0
Create: 13:37:59 (1306755479)
Write: 14:02:36 (1306756956)
Access: 00:00:00 (1306706400)Ergebniss in 2010 ist schlicht und einfach falsch:
_MSC_VER: 1600
Now: 14:02:33 (1306756953)
_daylight=1
_dstbias=-3600
_timezone=28800
test.txt: 0
Create: 14:37:59 (1306759079)
Write: 15:02:34 (1306760554)
Access: 01:00:00 (1306710000)Visual Studio 2008 Version 9.0.30729.1 SP
Compiler Options:
/Od /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /nologo /c /ZI /TP /errorReport:prompt
Visual Studio 2010 Version 10.0.40219.1 SP1Rel
Compiler Options:
/ZI /nologo /W3 /WX- /Od /Oy- /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Debug\Dateidatum.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue
Leider finde ich bei _findfirst() keine Informationen zu dem Thema und auch Google oder die Forensuche haben keine brauchbaren Ergebnisse geliefert.
Kann dieses Problem jemand reproduzieren?
Vielen Dank,
Andreas
Antworten
-
Mittlerweile hab ich einen Thread gefunden der offenbar ein ähnliches Problem behandelt:
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/7f3e17de-201a-4793-afd1-d1bc75e7d462
Also Lösung kann man entweder FindFirstFile() verwenden undn die FILETIME Struktur mittels FileTimeToSystemTime() und SystemTimeToTzSpecificLocalTime() und mktime() in time_t umrechnen):time_t filetime2time_t(FILETIME ft) { SYSTEMTIME stUTC, stLocal; FileTimeToSystemTime(&ft, &stUTC); SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); struct tm tm; memset(&tm, 0, sizeof(tm)); tm.tm_year = stLocal.wYear - 1900; tm.tm_mon = stLocal.wMonth - 1; tm.tm_mday = stLocal.wDay; tm.tm_hour = stLocal.wHour; tm.tm_min = stLocal.wMinute; tm.tm_sec = stLocal.wSecond; // + ((stLocal.wMilliseconds >= 500) ? 1 : 0); tm.tm_isdst = -1; time_t result = mktime(&tm); return result; }
oder man verwendet die direkte Umrechnung:
time_t filetime2time_t(const FILETIME& ft) { ULARGE_INTEGER ull; ull.LowPart = ft.dwLowDateTime; ull.HighPart = ft.dwHighDateTime; return ull.QuadPart / 10000000ULL - 11644473600ULL; }
und wenn man den alten Code beibehalten möchte kann man auch ganz einfach folgendes machen:
// In VisualStudio 2010 muß die Sommerzeit korrigiert werden #ifdef _MSC_VER >= 1600 long dstbias = 0; _get_dstbias(&dstbias); fd.time_create += dstbias; fd.time_write += dstbias; fd.time_access += dstbias; #endif
Ich werde die letztere Methode verwenden um mein Problem zu lösen.
- Als Antwort markiert Andreas Hammerschmidt Montag, 30. Mai 2011 13:14