Zeitstempel in Directorys und Dateien setzen
-
In einem Kopierprogramm möchte ich für die kopierten Dateien und Directorys auch den Zeitstempel (Datum und Uhrzeit) setzen. In diesem Fall geht es darum, Directorys und Dateien aus einem Disketten.IMG auf eine Festplatte (oder USB-Gerät) zu kopieren.
Datum und Uhrzeit werden aus dem Disketten-DIR ermittelt und liegen als String vor "tt.mm.jjjj hh:MM:ss".
So will ich das in ein neu angelegtes Directory übernehmenDirectoryInfo diNeu1 = Directory.CreateDirectory(dr.pNameL); // DIR erstellen //------------------------------------------------ // Datum und Uhrzeit in Directory übernehmen //------------------------------------------------ DirectoryInfo diNeu = new DirectoryInfo(dr.pNameL); DateTime dDIR = DateTime.Parse(dr.pDateTime); // "23.04.2023 08:24:24" diNeu.CreationTime = dDIR; // "23.04.2023 08:24:24" wird im Debugger angezeigt diNeu.CreationTimeUtc = dDIR; diNeu.LastAccessTime = dDIR; diNeu.LastAccessTimeUtc = dDIR; diNeu.LastWriteTime = dDIR; diNeu.LastWriteTimeUtc = dDIR;
Wenn ich mir das erstellt Directory ansehe, dann stimmt das Datum, als Uhrzeit wird jedoch statt 08:24:24 => 10:24:24 ausgegeben, also 2 Stunden später. Da muss doch JEMAND mit der Stundenangabe etwas ungewollt manipulieren, ich denke an SOMMER/WINTER-Zeit oder greenwich time.
Kann man Einfluss darauf nehmen, dass die Zeit so eingestellt wird, wie vorgegeben ohne Stunden-Manipulation ?Bei den Dateien mache ich das ähnlich, auch dort ist der Stunden-Verfälscher am Werk.
//------------------------------------------------ // Datum und Uhrzeit in Ausgabedatei übernehmen //------------------------------------------------ FileInfo fi = new FileInfo(FileNamen[i].pNameL); DateTime dDIR = DateTime.Parse(FileNamen[i].pDateTime); fi.CreationTime = dDIR; fi.CreationTimeUtc = dDIR; fi.LastAccessTime = dDIR; fi.LastAccessTimeUtc = dDIR; fi.LastWriteTime = dDIR; fi.LastWriteTimeUtc = dDIR;
-
Ja, das hat mit Sommer-/Winterzeit sowie den verschiedenen Dateisystemen (FAT, NTFS) zu tun, s.a. die für das freie Kopierprogramm FreeFileSync verfügbare Option: Daylight Saving Time (Windows)
-
@Th69 ,
ich glaube ich habe es jetzt gefunden.
Ich darf die Utc Zeiten nicht setzen//------------------------------------------------ // Datum und Uhrzeit in Ausgabedatei übernehmen //------------------------------------------------ FileInfo fi = new FileInfo(FileNamen[i].pNameL); DateTime dDIR = DateTime.Parse(FileNamen[i].pDateTime); fi.CreationTime = dDIR; fi.LastAccessTime = dDIR; fi.LastWriteTime = dDIR;
-
Stimmt, das ist mir nicht aufgefallen, daß du jeweils beide Zeiten setzt (und dann nur die letzte gilt).
Besser wäre m.E. jedoch, du würdest überall nur die UTC-Zeiten (anstatt der lokalen Zeit) benutzen.
-
Ideal wäre die Zeit als UTC von der Quelle zu bekommen und dann wieder als UTC zu schreiben. Blöd dabei ist bloss dass z.B. FAT (=typisches File-System für PC Disketten) für Timestamps die lokale Zeit verwendet. D.h. man kann die UTC-Zeit einfach nicht auslesen. Man muss also wissen mit welcher Zeitzone die Einträge geschrieben wurden. Bzw. wenn man es nicht weiss, muss man sich halt eine aussuchen.
-
@hustbaer
ich möchte eigentlich nur erreichen, wenn dort als Zeit 08:34 steht, dass dann beim Duplikat auch 08:34 steht. Manche Compare-Programme prüfen ja auch, ob der Zeitstempel übereinstimmt. Ob die Datei 08:34 Uhr oder 09:34 Uhr erstellt wurde, ist ja eigentlich völlig uninteressant. Bei den Disketten gibt es nur ein Datum und eine Uhrzeit.mfg Hartmut
-
Was passiert, wenn du direkt über die WINAPI gehst und die Zeitstempel per
GetFileTime
undSetFileTime
liest/schreibst?
-
@DocShoe
muss ich probieren - Danke für den Hinweis.Jetzt habe ich ja noch etwas entdeckt.
Wenn ich meine Diskette mit den zwei Dateien per DIR Kommando anschaue, dann sehe ich dort folgende Zeiten:29.12.1998 11:17 653 EFCW.LIC 05.12.1998 19:32 671.735 SETUP.EXE
Wenn ich die gleiche Diskette zur gleichen Zeit mit dem Explorer anschaue, dann sehe ich folgendes:
EFCW.LIC 29.12.1998 10:17 SETUP.EXE 05.12.1998 18:32
Offenbar sind sich DIR und EXPLORER selbst nicht einig, welche Zeit nun stimmt.
So sieht es im Directory der Diskette / der IMG-Datei aus
002600: 45 46 43 57 20 20 20 20 4C 49 43 20 00 0F 40 5A :EFCW LIC ..@Z: 002610: 9D 25 BD 4E 00 00 3B 5A 9D 25 02 00 8D 02 00 00 :.%.N..;Z.%......: ----- ----- Time Date TIME: 3B 5A = 0x5A3B = 0101 1010 0011 1011 ------#######++++++ Stunde Minute DoppelSek = 11:17:54 002620: 53 45 54 55 50 20 20 20 45 58 45 20 00 93 40 5A :SETUP EXE ..@Z: 002630: 9D 25 BD 4E 00 00 09 9C 85 25 04 00 F7 3F 0A 00 :.%.N.....%...?..: ----- ----- Time Date TIME: 09 9C = 0x9C09 = 1001 1100 0000 1001 ------#######++++++ Stunde Minute DoppelSek = 19:32:18
Das DIR-Kommando zeigt die Zeit, wie sie gespeichert ist, der Explorer schwindelt => eine Stunde weniger.
Rechnet er die Sommerzeit wieder in Normalzeit um ?
Das Datum ist jeweils Dezember 1998, also keine Sommerzeit.Es gibt eine Menge Dinge, wo die Zeit eine Rolle spielt.
Wann beginnt das Kino,
wann fährt der Bus oder der Zug ab
u.v.a.m.Deshalb ist es sehr lästig, wenn Windows bei Zeitanzeigen (und Abspeicherungen) dort eingreift.
Wenn ich einen Treff um 11°° vereinbare, dann meine ich die aktuelle Zeit, und nicht die, die gerade auf der Rückseite des Mondes gilt.
---- Ergänzung ---
Jetzt habe ich mir die Kopien der beiden Dateien auf der Festplatte auch mit DIR und EXPLORER angeschaut, da sieht es so aus:
DIR:29.12.1998 12:17 653 EFCW.LIC 05.12.1998 20:32 671.735 SETUP.EXE
EXPLORER:
EFCW.LIC 29.12.1998 11:17 SETUP.EXE 05.12.1998 19:32
Es ist also nahezu unmöglich, der Kopie einen identischen Zeitstempel der Originaldatei mitzugeben.
-
Oder der Explorer zeigt UTC und DIR zeigt localtime an. Der 29.12. liegt in der Winterzeit und hat also UTC +1:00.
-
Sind die Kopien vor dem fix (Nicht die UTC Member setzen) erstellt worden oder danach?
Weil wenn vor dem Fix, dann erklärt es den Unterschied von einer Stunde..Und du ziehst hier die falschen Schlussfolgerungen. Der Zeitstempel im Dateisystem ist mit sehr hoher Wahrscheinlichkeit richtig.
Aber die Interpretation des Wertes ist halt je nach tool unterschiedlich.
Und zu beziehst deine Schlussfolgerung, dass das mit den Zeitstempeln so ein Problem sei auf Werte, welche interpretierten und in einen für den Menschen lesbaren Darstellung überführt wurden.Ansonsten vergleich mal was dir/explorere für Zeitstempel zeigen, wenn du die Dateien aus dem image via robocopy kopierst (falls das image als virtuelles laufwerk "gemounted" ist)
Denn in der default Einstellungen kopiert robocopy die Zeitstempel mit.
-
@hkdd sagte in Zeitstempel in Directorys und Dateien setzen:
Wenn ich einen Treff um 11°° vereinbare, dann meine ich die aktuelle Zeit, und nicht die, die gerade auf der Rückseite des Mondes gilt.
Ja, richtig.
Der Vergleich ist aber unsinnig.
Eine "create-time"/"modification-time" ist ja keine aktuelle Zeit die nur jetzt, heute und hier Sinn macht. Und damit sie überall & zu jeder Zeit korrekt interpretiert werden kann, muss man sie einfach als UTC abspeichern. Dann kann die immer richtig angezeigt werden. Anders würde dabei nur Quatsch rauskommen. Genau so wenn du mit jemandem aus einer anderen Zeitzone ein remote Meeting vereinbarst, ihm aber nicht sagst welche Zeitzone du für die Uhrzeit verwendest. Das wird wenn dann auch nur zufällig funktionieren.
Angenommen ich habe eine Datei in England gespeichert, am 1.1.2000 um 12:00 mittags. Zu dem Zeitpunkt war es bei uns 13:00. Wenn mir mein System jetzt 12:00 als lokale Zeit anzeigen würde, dann wäre das falsch. Denn in meiner Zeitzone war es halt 13:00. Und das unabhängig davon ob ich zu dem Zeitpunkt wo ich mir den Zeitstempel ansehe gerade Sommerzeit habe oder nicht - denn damals, als die Datei geschrieben wurde war ja keine Sommerzeit aktiv.
Was die Sache jetzt etwas fummelig macht, ist dass Programme wie Explorer für alle File-bezogenen Zeitstempel den selben Code verwenden -- und der geht davon aus dass die Zeitstempel in UTC vorliegen. Damit Zeitstempel die auf dem Datenträger in lokaler Zeit gespeichert wurden korrekt angezeigt werden, muss also irgendwo von lokaler Zeit auf UTC zurückgerechnet werden. Zur Anzeige wird dann wieder von UTC auf lokale Zeit umgerechnet. Und das machen manche Programme leider falsch. Richtig wäre anhand der lokalen Zeitzone den UTC-Offset zu berechnen der zum Zeit des Zeitstempels aktiv war, und diesen dann zur Umrechnung zu verwenden. Manche Programme holen sich aber einfach nur den aktuellen UTC-Offset und machen die Umrechnung damit. Dabei kann dann durch die Sommerzeit ein Fehler von einer Stunde passieren.
Deine Beispiel-Zeiten sind im Winter, d.h. da war Normalzeit, also +1. Aktuell haben wir Sommerzeit, also +2.
Die korrekte Umrechnung wäre:Lokal 11:17 -> UTC mit -1 = 10:17
UTC 10:17 -> Lokal mit +1 = 11:17Falsche Umrechnung in Schritt 1 wäre:
Lokal 11:17 -> UTC mit -2 = 09:17
UTC 09:17 -> Lokal mit +1 = 10:17Falsche Umrechnung in Schritt 2 wäre:
Lokal 11:17 -> UTC mit -1 = 10:17
UTC 10:17 -> Lokal mit +2 = 12:17D.h. der Fehler passiert in Schritt 1. Das entspricht auch dem dokumentierten Verhalten der Win32 API: https://learn.microsoft.com/en-us/windows/win32/sysinfo/file-times#file-times-and-daylight-saving-time
Sad but true.Windows Explorer (der nur Schritt 2 ausführt) macht dagegan alles richtig. Das einzige was man dort verbessern könnte, wäre einen Workaround für FAT Datenträger einzubauen, der die falsche Umrechnung in der Win32 API nachträglich korrigiert.
Deshalb ist es sehr lästig, wenn Windows bei Zeitanzeigen (und Abspeicherungen) dort eingreift.
Sehe ich anders. Alle modernen File-Systeme speichern Zeitstempel in UTC. Weil wie bereits gesagt alles andere keinen Sinn macht. Anzeige wollen die meisten Benutzer aber in lokaler Zeit haben - was auch verständlich ist. Es muss also umgerechnet werden.
Das einzige was Windows hier falsch macht, ist dass es bei File-Systemen die lokale Zeitstempel speichern falsch von der gespeicherten Lokalzeit auf UTC umrechnet. Das ist IMO wirklich doof.
Es ist also nahezu unmöglich, der Kopie einen identischen Zeitstempel der Originaldatei mitzugeben.
Das Problem ist dass der Begriff "identisch" hier mMn. einfach nicht anwendbar ist. Wie willst du einen lokalen Zeitstempel in einer unbekannten Zeitzone in einen "identischen" UTC Zeitstempel umwandeln? Das kann nicht gehen. Du kannst maximal einen passenden UTC Zeitstempel wählen, so dass nach Umrechnung in eine bestimmte Zeitzone wieder das selbe rauskommt. Wenn du dann aber auf einen anderen PC gehst, der eine andere Zeitzone verwendet, und die Daten dort ansiehst, wird was anderes rauskommen.
-
@hkdd sagte in Zeitstempel in Directorys und Dateien setzen:
---- Ergänzung ---
Jetzt habe ich mir die Kopien der beiden Dateien auf der Festplatte auch mit DIR und EXPLORER angeschaut, da sieht es so aus:
DIR:29.12.1998 12:17 653 EFCW.LIC 05.12.1998 20:32 671.735 SETUP.EXE
EXPLORER:
EFCW.LIC 29.12.1998 11:17 SETUP.EXE 05.12.1998 19:32
Das liegt vermutlich daran dass
dir
falsch von UTC auf Lokalzeit umrechnet - also auch mit dem aktuellen Offset statt mit dem Offset der damals aktiv war. Wie gesagt, Explorer macht diesen Teil richtig. Und sobald die Datei auf einem NTFS Volume liegt, gibt es den ersten Schritt der Umrechnung nicht mehr.D.h. wenn du es möglichst "korrekt" machen willst, dann mach es so dass Explorer die gewünschte Zeit anzeigt.
-
@hustbaer sagte in Zeitstempel in Directorys und Dateien setzen:
mach es so dass Explorer die gewünschte Zeit anzeigt.
Mir geht es nicht um die (Schwindel-/Umrechnungs-)Anzeige, sondern um die Zeit, die in der Datei bzw. dem Directory gespeichert ist. Ich habe ein Programm gemacht, mit dem ich lediglich die Ordner und Dateien hinsichtlich Name, Größe, Datum und Uhrzeit vergleiche. Das geht bei vielen Dateien ziemlich schnell, da die Dateien selbst nicht gelesen werden müssen, nur die Directorys, was ja mit C# sehr schön zu realisieren ist.
Ich habe von vielen Dateien auf externen HDD Sicherheitskopien, z.B. alle Dateien im VS2022 Ordner. Da kann ich also sehr schnell feststellen, ob und was geändert wurde. Deshalb sollte bei Kopieren von Dateien auch der Zeitstempel der Ursprungsdatei in die Zieldatei 1-zu-1 übernommen werden. Natürlich könnte man bei der Überprüfung eine Stunde oder zwei Stunden tolerieren, wenn Minuten und Sekunden stimmen. Das machen auch manche Programme so.
Viele Zeitstempel, die wichtig sind, gehören zu Fotos aus den Digitalkameras. Bei einer Reise z.B. nach Australien muss man dort die Ortszeit einstellen und später erkennt man aus dem Zeitstempel, den manche Kameras auch sichtbar im Bild selbst hinterlegen (analog Polizeifotos), wann (Datum und Uhrzeit) man an dem zu sehen Ort war.
In NTFS-Directorys ist ja viel Platz für alle möglichen Zeiteintragungen. Die Digitalkameras benutzen u.U. Speicherkarten, die FAT12/FAT16-formatiert sind. Da gibt es nur EINEN Zeitstempel. Zusätzlich hat man da noch (falls es die Kamara macht und kann) die Exif-Informationen, die man beim Kopieren auf jeden Fall 1-zu-1 kopiert, die aber beim Bearbeiten eines Bildes (je nach Bildbearbeitungsprogramm) evtl. verloren gehen.
--- <Ergänzung> ---
Ich habe auf meinem PC in VMWare noch Win7-Ultimate, WIn8.1 und WinXP installiert.
Dort werden für die Dateien folgende Zeiten angezeigt:
Win7 -DIR: EFCW.LIC=12:17 SETUP.EXE=20:32 EXPLORER: EFCW.LIC=11:17 SETUP.EXE=19:32 Win81-DIR: EFCW.LIC=12:17 SETUP.EXE=20:32 EXPLORER: EFCW.LIC=11:17 SETUP.EXE=19:32 WinXP-DIR: EFCW.LIC=12:17 SETUP.EXE=20:32 EXPLORER: EFCW.LIC=12:17 SETUP.EXE=20:32
Da der XP-Explorer offenbar keine Zeitumrechnungen macht und die Zeit so anzeigt, wie sie gespeichert ist (analog DIR), sind die gespeicherten Zeiten alle um eine Stunde nach vorn gesetzt, also angebliche UTC-Zeiten wurden in Deutsche Ortszeiten (+1 Stunde) umgerechnet, und zwar bereits in meinem Programm bei diesen Befehlen
//------------------------------------------------ // Datum und Uhrzeit in Ausgabedatei übernehmen //------------------------------------------------ FileInfo fi = new FileInfo(FileNamen[i].pNameL); // pDateTime = "29.12.1998 11:17:54" bzw. "05.12.1998 19:32:18" DateTime dDIR = DateTime.Parse(FileNamen[i].pDateTime); // Hier ist es 11:17 und 19:32 fi.CreationTime = dDIR; // // Hier wird es zu 12:17 und 20:32 fi.LastAccessTime = dDIR; fi.LastWriteTime = dDIR;
Kann man da nicht festlegen, dass es sich bereits um die richtige Zeit (11:17 und 19:32) handelt (Lokal-Zeit) und nichts umgerechnet werden soll/darf/muss.
-
Deine Annahme ist, dass wenn der Timestamp identisch ist, dass man keine weiteren checks mehr machen muss, ist leider fehlerhaft.
Wie du mit deinem Tool selbst siehst, kann man recht einfach die Timestamps von Dateien ändern.
Daher ist das kein Kriterium um zu sagen die Dateien sind identisch!Was viele backup tools machen, wenn sie ein inkrementelles backup durchführen, ist genau das gegenteil was du machen möchtest.
Wenn ein backup tool feststellt, dass von einer Datei der Timestamp sich verändert hat (gegenüber der Datei in der Backup location), dann nehmen diese an, dass die Datei sich verändert hat und nehmen diese Datei direkt auf in die liste der Dateien die gebackupt werden müssen.Wenn der Timestamp identisch ist, dann prüfen sie ob die Daten in der Datei sich verändert hat. Und da gibt es verschiedene Verfahren um schon früh festzustellen ob es Unterschiede gibt (nicht gleicheit!) ohne die Datei komplett neu zu lesen.
Um wirklich 100% festzustellen, dass die Dateien identisch sind, ist nur möglich wenn diese byteweise verglichen oder filehashes genutzt werden.
-
@firefly sagte in Zeitstempel in Directorys und Dateien setzen:
byteweise verglichen
das ist richtig, ein Programm für den byteweisen Vergleich habe ich ja auch, das haben wir hier ausführlich diskutiert hinsichtlich der Laufzeit und verschiedenen Methoden des des Vergleiches zweier Byte-Arrays.
Ich habe z.B. alle meine Foto-JPG-Dateien in einem Ordner mit sehr vielen Unterordnern (ähnlich bei allen Musik- und Video-Dateien).
Hier ein Auszug aus dem DIR-Listing der JPG-Dateien:Anzahl der angezeigten Dateien: 94439 Datei(en), 140.373.917.678 Bytes 0 Verzeichnis(se), 1.687.689.732.096 Bytes frei 2.302 Verzeichnisse 94.439 Dateien
Wenn ich den Vergleich nur mit Name, Größe, Datum und Uhrzeit mache, dann dauert das wenige Minuten, ein komplette byteweiser Vergleich würde Stunden dauern.
Diese Dateien (Fotos, Musik, Videos, VS-Studio-Programmier-Dateien usw.) sind jeweils auf großen externen Festplatten gesichert. Ich will einmal im Monat feststellen, wo hat sich etwas geändert (eine Art Synchronisation) und daraufhin die Idendität herstellen. Das will ich aber nicht automatisch machen, sodern die Unterschiede selbst in Augenschein nehmen.Ich habe jetzt das Kopieren des Zeitstempels so abgeändert:
für Dateien//------------------------------------------------ // Datum und Uhrzeit in Ausgabedatei übernehmen //------------------------------------------------ FileInfo fi = new FileInfo(FileNamen[i].pNameL); CultureInfo deCultureInfo = CultureInfo.CreateSpecificCulture("de-DE"); DateTime dDIR = DateTime.Parse(FileNamen[i].pDateTime, deCultureInfo); fi.CreationTime = dDIR; fi.LastAccessTime = dDIR; fi.LastWriteTime = dDIR;
für Directorys
//------------------------------------------------ // Datum und Uhrzeit in Directory übernehmen //------------------------------------------------ DirectoryInfo di = new DirectoryInfo(FileNamen[i].pNameL); CultureInfo deCultureInfo = CultureInfo.CreateSpecificCulture("de-DE"); DateTime dDIR = DateTime.Parse(FileNamen[i].pDateTime, deCultureInfo); di.CreationTime = dDIR; di.LastAccessTime = dDIR; di.LastWriteTime = dDIR;
-- < Ergänzung> --
Ich habe nun in meinem Vergleichsprogramm (Name, Länge, Datum, Uhrzeit) alles möglche probiert. Ich habe direkt die Diskette als den einen Ordner ( A:\ ) und die Kopie auf der Festplatte D : \ als den anderen Ordner angegeben.
Ich kenne genau die Diskette, da steht die Uhrzeit 11:17:54.
In FileInfo der Datei auf A:\EFCW.LIC sind LastWriteTime= 10:17:54 und LastWriteTimeUtc= 09:17:54.
In FileInfo der Datei auf D:\EFCW.LIC sind LastWriteTime= 11:17:54 und LastWriteTimeUtc= 10:17:54.
Nach dem Motto "Der Klügere gibt nach" habe ich nun eingebaut, das eine oder zwei Stunden Differenz akzeptiert werden, wenn Minuten und Sekunden und Datum übereinstimmen. Ich habe keinen Weg gefunden, mit den Möglichkeiten von VS2022 die tatsächlich auf der Diskette gespeicherte Zeit = 11:17:54 auszulesen. Es sei denn, man liest die physischen Sektoren und wertet selbst die Informationen im Disketten-Directory aus.
-
@hkdd sagte in Zeitstempel in Directorys und Dateien setzen:
Da der XP-Explorer offenbar keine Zeitumrechnungen macht und die Zeit so anzeigt, wie sie gespeichert ist (analog DIR), sind die gespeicherten Zeiten alle um eine Stunde nach vorn gesetzt
Nein, das stimmt nicht. Auch der Windows-XP Explorer macht ne Umrechnung. Und zwar von UTC nach lokaler Zeit. Er macht sie nur falsch.