Fragensteller
Sommer-Winterzeit

Frage
-
Hallo zusammen,
habe ein kleines Problem mit der Sommer/Winterzeit-Umstellung. Ein VFP-Programm liest Daten-Files ein. Darunter auch das File-Datum. Klappt alles prima. Das File-Datum ist ein Kriterium um eine Veränderung am File festzustellen. Seit der Zeitumstellung werden jetzt alle Files im Änderungsdatum um 1 Stunde später angezeigt
Hat der Fux eine Möglichkeit korrekt damit umzugehen? Gibt es Bordmittel, die ein File-Datum (aus ADIR) automatisch auf UTC umzurechnen?
Oder muß man dieses Problem auf andere Weise lösen.
Bin für jeden Tip dankbar.
Gruß
Christoph
Donnerstag, 3. November 2016 14:54
Alle Antworten
-
Hi Christoph,
Du hast doch in der ADIR() - Function schon als 4. die Zeitangabe.
Also z.B. =adir(dbfdateien,"*.dbf")
cZeit = dbfdateien(1,4) = zuletzt modifizierte Zeit der ersten Datei
und cStunde = substr(cZeit,1,2) ist die Stunde
Ansonsten schau in der Hilfe mal nach der Datetime()-Funktion
Unten unter References findest Du dann die ganzen anderen Datums-Zeit-Funktionen
Nebenbei : Du kannst beim Fuchs zum Datum die Tage dazuaddieren
also date() + 30 bringt Dir das korrekte Datum von heute in 30 Tagen.
Aber das nur am Rande :-)hth
Horst
Freitag, 4. November 2016 08:03 -
Hallo zusammen,
erstmal vielen Dank für eure Antworten.
Ich habe irgendwo gelesen, daß VFP die DatumZeit-Werte der Dateien grundsätzlich über die Zeiteinstellung des BS interpretiert und sich somit der Zeitstempel einer Datei je nach Sommer/Winterzeit um eine Stunde (bzw. 3600 Sekunden) unterscheiden kann. Da ich neben dem Zeitstempel der Dateien auch noch Größe, Verzeichnis, Name der Datei als Unterscheidungsmerkmal heranziehe, habe ich jetzt folgende Lösung gebastelt:
Bei der Prüfung, ob ich eine bestimmte Datei schon inventarisiert habe (Dateiinformationen in einer Tabelle) prüfe ich auf Sommerzeit und auf Winterzeit (+1 Stunde) . D. h. wenn eine Datei beim Scan die Uhrzeit 14:37 hat, suche ich in der Tabelle nach 13:37, 14:37 und nach 15:37; wenn einer der drei Einträge (mit einigen anderen Einträgen) vorhanden ist, wird diese Datei übersprungen. Die Wahrscheinlichkeit, daß eine besitmmte Datei mit kgleicher Größe und exakt mit einer Stunde Zeitdifferenz abgespeichert wird und somit nicht erfasst werden würde (weil der User vielleicht ohne automatische Zeitumstellung arbeitet) ist nahezu Null. Somit bin ich von der Zeitumstellung unabhängig und ich hab mir einigen Programmieraufwand gespart.
Nochmals vielen Dank.
Gruß
Christoph
Freitag, 4. November 2016 14:51 -
Eine generelle Lösung ist das natürlich nicht da ich Verarbeitungen kenne wo die von Dir beschriebene Wahrscheinlichkeit nicht Null wäre. Sonst hättest Du noch z.B. die Möglichkeit die Inventarisierung zu loggen, also in eine Tabelle mitzuschreiben welche Datei inventarisiert ist. Und es gäbe noch andere Varianten aber ohne das System zu kennen wären das Ratschläge ins Blaue. Aber Du kennst ja das System und wenn das so funktioniert ist es okay.
Auf jeden Fall waren das prima Tipps von Tom ! Allzuviel Arbeit hätte man mit diesen Codes ja nicht mehr.
schönes WE
Horst
Freitag, 4. November 2016 15:23 -
Moin, moin
noch eine Anmerkung zum Workflow.
Wir übernehmen Dateien von mehreren Messgeräten aus mehreren Verzeichnissen von mehreren Niederlassungen.
Dabei bekommt jede Datei beim Einlesen einen unternehmsweit eindeutigen primarykey (int), der wird vor den dateinamen gesetzt und die datei umbenannt (xx.wsk->0001234567_xx.wsk). Beim Einlesen werden die Werte verarbeitet und die Datei mitarchiviert (SQL-Server, varchar(max)) und dann gelöscht, teilweise lassen wir noch die SPS Zip Routinen drüber laufen. Zusätzlich speichern wir noch die Herkunft, timestamp der verarbeitung,..
So loggen wir nicht nur WANN etwas übernommen wurde, sondern auch WAS. Und der Speicherplatz ist mindestens identisch zu einer Dateiablage (ohne die Probleme mit gleichen Dateinamen,..)
Grüße
tom
Montag, 7. November 2016 08:25 -
Was Du wirklich brauchst ist ja nur eine Aussage, ob zwei Filetimes gleich sind oder unterschiedlich. Also speichere Dir doch die Filetime statt Systemtime. Filetimes sind immer UTC, während ADIR die Zeit auf Systemzeit umrechnet, deswegen der Sprung, aber Filetimes bleiben UTC. Das Problem ist wirklich, dass UTC->Systemtime nicht berücksichtigt, welcher Bias zu der UTC bestand, dazu müßte die Umwandlung eine Nachschlagetabelle aller Umstellungszeitpunkte haben, die Umwandlung geschieht immer mit dem aktuellen Bias.
Folgendes könnte Dir gut helfen:
http://www.news2news.com/vfp/?example=171&function=262
Der Code, speziell GetLastWriteTime, wandelt die Filetime gar nicht erst in einen VFP Datetime Wert um. Zum Vegleich wird die CompareFileTime API Funktion genutzt. Statt lcLastWriteTm kannst Du ja auch lcCreationTm oder lcLastAccessTm zurückgeben, was auch immer Du brauchst. Diese Strings lassen sich prinzipiell in einem C(8) Feld speichern, um wirklich binär zu speichern wäre ein qFiletime Q(8) Feld angebracht, in dass Du CREATEBINARY(m.lcFiletime) speicherst und was Du dann mit lcFiletime=''+ qFiletime ausliest, bevor Du die CompareFileTime API Funktion damit und mit der aktuellen FileTime eines Files speist.
Bye, Olaf.
Olaf Doschke - TMN Systemberatung GmbH
PS: Ein Zusatztipp
Ich habe gerade mal mit LastAccessTime gespielt und die Zeit änderte sich nicht, obwohl ich z.B. eine TXT-Datei geöffnet hatte.
Falls Du das Verhalten auch beobachtest, lies einmal folgendes:
http://www.groovypost.com/howto/microsoft/enable-last-access-time-stamp-to-files-folder-windows-7/Ich fand mittels fsutil behavior query disablelastaccess heraus, dass es auf 1 war, also der letzte Zugriff nicht protokolliert wurde. Nachdem ich es auf 0 gesetzt hatte (enabled = nicht disabled), kriege ich mit GetFileTime die letzte Zugriffszeit, wobei das Eigenschaftsfenster der Datei das nicht so zeitnah mitzieht, wie die GetFileTime Funktion, andersherum wäre ungünstiger, also gut so. Man kriegt also u.U. auch ohne Umbennennug, Verschiebung oder Kopie der Datei nicht nur heraus, wann sie zuletzt geändert wurde (LastWriteTime/Schreibzugriff), sondern sogar, wann eine EXE zuletzt gestartet, eine DBF oder DOC(X) zuletzt geöffnet wurde, etc., das hängt aber stark von dieser Fileysystem-Einstellung ab.
- Bearbeitet Olaf Doschke Dienstag, 8. November 2016 13:43
Dienstag, 8. November 2016 07:46 -
Hallo Olaf,
exakt, das ist das Problem in meinem Programm.
Ich durchforste in dem Programm eine Grundmenge von ca. 17000 Files. Wenn ich die Routinen aus deinem Link betrachte, much ich jedes Files öffnen, damit ich an die Zusatzinfos komme (... openfile (... ). Ich bin mal gespannt, wie sich der Zeitbedarf hierfür darstellt.
Ich werde die Funktionen mal testen und Rückmeldung geben.
Gruß
Christoph
Dienstag, 8. November 2016 14:01 -
Ja, wäre interessant.
Zur Info: Es geht lediglich um ein Filehandle, es wird nicht die Datei ausgelesen.
Was ich eben mal ausprobiert habe: Wenn eine Datei gerade exklusiv geöffnet ist (z.B. mittels VFP FOPEN(name,12)) kann OpenFile auch kein Filehandle kriegen, während ADIR die Dateiinfos noch abholen kann. Eine Auswirkung auf das ganze hat es also schon, aber exklusiver Dateizugriff ist eher seltener Hinderungsgrund.
Was Du machen könntest und was völlig unabhängig von Files und Handles ist, wäre den Bias (DECLARE integer GetTimeZoneInformation IN Win32API STRING @ TimeZoneStruct) zu speichern und beim Abgleich zu berücksichtigen oder daraus die UTC Filezeit zu rechnen und zu speichern, wodurch der Abgleich am Folgetag unabhängig von Zeitumstellungen wird.
Olaf Doschke - TMN Systemberatung GmbH
Dienstag, 8. November 2016 14:18 -
Habe noch ein kleines Problem mit GetLastWriteTime; eigentlich sollte doch der Rückgabewert dieser Funktion vom Type String sein, oder? Bei mir kommt allerdings alles Mögliche raus, nur kein String.
Müsste ich noch irgendwas vorher deklarieren?
Gruß
Christoph
Dienstag, 8. November 2016 14:45 -
Hallo zusammen,
habe es mittlerweile auf der Reihe (zumindest fast). Ich glaubte, einfach den Beispielcode aus
http://www.news2news.com/vfp/?example=171&function=262
verwenden zu können. Hierdrin fehlen allerdings noch die entsprechenden Konvertierungen. ich habe dann das Beispiel aus
http://www.news2news.com/vfp/?example=177&function=262
genutzt und entsprechend 'abgespeckt'. Funktioniert. Prima.
Allerdings habe ich jetzt folgenden Unterschied:
Die Anzahl der Sekunden im LstWriteTime unterscheiden sich von der Anzahl der Sekunden, welche durch ADIR ausgelesen werden um 2 - (Zeitstempel von ADIR ist immer um 2 Sekunden größer).Aus meiner Sicht liegt hier ADIR falsch, da sich die Angabe des Sekundenwertes aus einem Dataimanager des BS von ADIR in der gleichen Weise unterscheiden.
Hat jemand ne Erklärung hierfür?
Gruß
Christoph
Mittwoch, 9. November 2016 13:43 -
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724320(v=vs.85).aspx
Quote: Not all file systems can record creation and last access times and not all file systems record them in the same manner. For example, on FAT, create time has a resolution of 10 milliseconds, write time has a resolution of 2 seconds, and access time has a resolution of 1 day (really, the access date).
zu Deutsch, die Zeiten haben je nach Dateisystem unterschiedliche granularität oder Exaktheit. Das erklärt nicht einen Unterschied von 2 Sekunden von ADIR vs GetLastWriteTime. Probiere es vielleicht zum verlgeich mal andersherum, nicht dass Du die Zeit durch ihre Abfrage selbst beeinfluss. Wie Du ja schon erkannt hast öffnet man die Files zur Nutzerung der API Funktionen, während ADIR auch auf direcctories und files funktioniert, die in exklusivem Gebrauch sind.
Wobei das öffnen einer Datei per se keine Modifkation/Schreibzugriff ist.
Tschüß, Olaf.
Olaf Doschke - TMN Systemberatung GmbH
Mittwoch, 16. November 2016 14:38 -
Hallo Olaf,
vielen Dank für deinen Hinweis. Nach ettlichem Programmieren und Testen bin ich final zum Entschluß gekommen, daß das Einlesen des Filedatums (via ADIR) und das Prüfen des Dateidatums/Zeitstempels innerhalb einer Tabelle (Zeit +/- 1 Stunde) am schnellsten geht (15000 Files aus dem Netzwerk in ca. 22 Sekunden bei 3-fachem 'seek'; selbst ein einfacher 'seek' macht sich im Zeitbedarf kaum bemerkbar).
Das Auslesen und Aufbereitung der Daten via Kernel-Funktion ist von der Eindeutigkeit am sichersten. Kein Zweifel. Der dafür benötigte Zeitaufwand liegt allerdings bei der gleichen Datenmenge bei über 8 Minuten. Es kann sein, daß sich diese Routinen etwas verbessern lassen, aber für meine Anwendung ist der Zeitbedarf ein wichtiger Aspekt.
Nochmals vielen Dank für die Hinweise
Gruß
Christoph
Mittwoch, 16. November 2016 16:17 -
OK, noch ein kleiner Tipp zum herausfinden der Bias-Richtung +/- 1 Stunde:
API Funktion GetSystemTime liefert immer UTC Zeit, unbeeinflusst von Zeitumstellungen eine fortlaufende Referenzzeit.
Wenn Du das mit DATETIME() abgleichst und die Differenz von gestern auch kennst, weiß Du ob und in welche Richtung sich die Uhrzeit zuletzt geändert hat. Obwohl es auch leichte Merkregeln für Frühling/Herbst gibt, in welche Richtung es geht.? UTC() FUNCTION UTC() LOCAL lcBuffer lcBuffer = REPLI (Chr(0), 16) && SYSTEMTIME structure = GetSystemTime (@lcBuffer) wYear = CToBin(SUBSTR(lcBuffer, 1, 2),"2RS") wMonth = CToBin(SUBSTR(lcBuffer, 3, 2),"2RS") wDay = CToBin(SUBSTR(lcBuffer, 7, 2),"2RS") wHour = CToBin(SUBSTR(lcBuffer, 9, 2),"2RS") wMinute = CTobin(SUBSTR(lcBuffer, 11, 2),"2RS") wSecond = CToBin(SUBSTR(lcBuffer, 13, 2),"2RS") lcDate = CHRTRAN(STR(wYear,4) + "-" + STR(wMonth ,2) + "-" + STR(wDay ,2), " ","0") lcTime = CHRTRAN(STR(wHour,2) + ":" + STR(wMinute,2) + ":" + STR(wSecond,2), " ","0") ltResult = Eval("{^"+lcDate + " " + lcTime+"}") RETURN ltResult EndFunc Function GetSystemTime(tcBuffer) Declare GetSystemTime In kernel32 String @lpSystemTime Return GetSystemTime(@tcBuffer) EndFunc
Olaf Doschke - TMN Systemberatung GmbH
Mittwoch, 23. November 2016 13:57