none
Dateidatum in VC++ 2008 und 2010 RRS feed

  • 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

     

     



    Montag, 30. Mai 2011 12:01

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.

    Montag, 30. Mai 2011 12:18