Ich danke schon mal für die Vorschläge.
Jens
Könnte es sich dabei um einen 32-bit-Unix-Timestamp handeln?
Falls ja, müsstest Du die vier Bytes in eine Long-Zahl einlesen
(Byte-Reihenfolge beachten) und in eine Excel-Datum-Zeit umrechnen.
Die untenstehende Funktion erledigt das. Sie korrigiert die Zeitzone
(GMT+1) und berücksichtigt alle deutschen Sommerzeiten. Wenn Du nur
aktuelle Datumswerte hast, reicht auch der erste Teil der If-Abfrage
(jahr>=1996). Siehe auch Links im Code.
Peter
Public Function UnixToExcel(unixtime As Long) As Date
'http://de.wikipedia.org/wiki/Sommerzeit#Deutschland
'http://www.ptb.de/de/org/4/44/441/sneu.htm
'http://www.ptb.de/de/org/4/44/441/salt.htm
Dim sommer As Variant
Dim dst As Variant
Dim jahr As Integer
UnixToExcel = CDate(unixtime/86400+25569) + TimeSerial(1,0,0)
jahr = Year(CLng(unixtime / 86400) + 25569.5)
If jahr >= 1996 Then
sommer = Array(Array(1, _
Format(DateValue("31.03." & jahr) _
- (DateValue("30.03." & jahr) Mod 7), _
"dd.mm.yyyy 02:00:00"), _
Format(DateValue("31.10." & jahr) _
- (DateValue("30.10." & jahr) Mod 7), _
"dd.mm.yyyy 02:00:00")))
ElseIf jahr >= 1980 Then
sommer = Array(Array(1, _
Format(DateValue("31.03." & jahr) _
- (DateValue("30.03." & jahr) Mod 7), _
"dd.mm.yyyy 02:00:00"), _
Format(DateValue("31.09." & jahr) _
- (DateValue("30.09." & jahr) Mod 7), _
"dd.mm.yyyy 02:00:00")))
Else
sommer = Array( _
Array(2,"11.05.1947 02:00:00","29.06.1947 01:00:00"), _
Array(1,"30.04.1916 23:00:00","01.10.1916 00:00:00"), _
Array(1,"16.04.1917 02:00:00","17.09.1917 02:00:00"), _
Array(1,"15.04.1918 02:00:00","16.09.1918 02:00:00"), _
Array(1,"01.04.1940 02:00:00","02.11.1942 02:00:00"), _
Array(1,"29.03.1943 02:00:00","04.10.1943 02:00:00"), _
Array(1,"03.04.1944 02:00:00","02.10.1944 02:00:00"), _
Array(1,"02.04.1945 02:00:00","16.09.1945 01:00:00"), _
Array(1,"14.04.1946 02:00:00","07.10.1946 02:00:00"), _
Array(1,"06.04.1947 03:00:00","05.10.1947 02:00:00"), _
Array(1,"18.04.1948 02:00:00","03.10.1948 02:00:00"), _
Array(1,"10.04.1949 02:00:00","02.10.1949 02:00:00"))
End If
For Each dst In sommer
If UnixToExcel >= CDate(dst(1)) - 0.4 / 86400 And _
UnixToExcel < CDate(dst(2)) - 0.4 / 86400 Then
UnixToExcel = UnixToExcel + TimeSerial(dst(0),0,0)
Exit For
End If
Next
End Function
Peter Schleif schrieb:
> Jens Unglaube schrieb am 29.08.2008 17:46 Uhr:
>> ich habe da viele Programmdateien im Hexadezimalformat, die ich in Excel
>> mit VBA einlesen will. [...] Mein problem ist nun eine 4Byte
>> Zeichenfolge hinter der sich ein Datum mit Zeit verbirgt. Im Hexeditor
>> bekomme ich diese Zeit auch angezeigt, aber wie mache ich das in
>> Excel-VBA? Der Type Date funktioniert nicht.
>
> Könnte es sich dabei um einen 32-bit-Unix-Timestamp handeln?
Die Dateien werden auf einen DOS 6 PC mit Win3.11 erzeugt. Ich denke es
wird dann eher nicht UNIX sein aber probieren kann man es ja mal.
>
> Falls ja, müsstest Du die vier Bytes in eine Long-Zahl einlesen
> (Byte-Reihenfolge beachten) und in eine Excel-Datum-Zeit umrechnen.
Das hatte ich schon probiert die Zahl, die dabei rauskam konnte ich aber
Excel nicht zuordnen, vor allem weil ja wenigstens eine Kommazahl
entstehen sollte. Was meinst du eigentlich mit Reihenfolge? Long hat
doch genau 4Bytes. Oder sollte man die Bytes erst noch in Bits ausgeben
lassen? Geht das überhaupt?
>
> Die untenstehende Funktion erledigt das. Sie korrigiert die Zeitzone
> (GMT+1) und berücksichtigt alle deutschen Sommerzeiten. Wenn Du nur
> aktuelle Datumswerte hast, reicht auch der erste Teil der If-Abfrage
> (jahr>=1996). Siehe auch Links im Code.
Die Dateien sind alle erst nach 2000 entstanden und ob Sommer oder
Winterzeit war ist nicht ganz so wichtig.
Beispiel für die Hex D9 04 B8 48 im Hex editor
als 32 Bit unsigned Long 1220019417
als 32 Bit Float 376870.78
als 32 Bit Time_t 14:16:57 29.08.2008
als Binary 11011001000001001011100001001000
Wirkliche Zeit war 07:16:57 29.08.2008
Jens
Jens Unglaube schrieb:
> Hallo Peter,
> vielen Dank für die schnelle Antwort
>
> Peter Schleif schrieb:
...
>> Könnte es sich dabei um einen 32-bit-Unix-Timestamp handeln?
>
> Die Dateien werden auf einen DOS 6 PC mit Win3.11 erzeugt. Ich denke es
> wird dann eher nicht UNIX sein aber probieren kann man es ja mal.
Es hat mir keine Ruhe gelassen und ich habe es probiert - es funktioniert.
mit dem ersten Code
UnixToExcel = CDate(unixtime / 86400 + 25569) + TimeSerial(-7, 0, 0)
1 in -7 geändert, erreiche ich genau was ich will.
Danke, Danke
Jetzt muss ich nur noch z.B. 7F 03 in 0111111100000011 umwandeln, hast
du da auch noch eine Idee?
Jens
Die Rreihenfolge in der die vier Bytes im Speicher/Datei stehen. Dein
Beispiel D9 04 B8 48 ergibt (als Hex-Zahl von links-nach-rechts
gelesen) 3640965192 und _nicht_ 1220019417. Auch deine
Binär-Darstellung stimmt nicht.
Die Zahl wurde vermutlich im Little-Endian-Format gespeichert und muss
darum als Hex-Zahl eigentlich 48B804D9 geschrieben werden. Das ergibt
auch tatsächlich 1220019417. Glücklicherweise berücksichtigen
System-Routinen die Byte-Reihenfolge und liefern automatisch die
richtige Dezimal-Zahl.
Peter
Super. Graturliere.
> mit dem ersten Code
> UnixToExcel = CDate(unixtime / 86400 + 25569) + TimeSerial(-7, 0, 0)
> 1 in -7 geändert, erreiche ich genau was ich will.
Vielleicht eine andere Zeitzone? GMT-7, statt GMT+1
> Jetzt muss ich nur noch z.B. 7F 03 in 0111111100000011 umwandeln, hast
> du da auch noch eine Idee?
Es gibt ein Add-In mit =DEZINBIN(). Aber soweit ich mich erinnere,
macht das Probleme bei längeren Zahlen. Wenn Du ohnehin schon mit VBA
arbeitest, kannst Du auch noch eine kleine rekursive Function dazunehmen.
Peter
MsgBox dec2bin(&H7F03)
MsgBox Format(dec2bin(&H7F03), String(16, "0"))
Function dec2bin(ByVal dez As Long) As String
If dez > 0 Then dec2bin = dec2bin(dez \ 2) & dez Mod 2
End Function
Peter Schleif schrieb:
> Jens Unglaube schrieb am 29.08.2008 23:49 Uhr:
>> Es hat mir keine Ruhe gelassen und ich habe es probiert - es funktioniert.
>
> Super. Graturliere.
>
Sorry, dass ich mich erst jetzt melde, aber ich bin das WE etwas in
Stress gewesen. Aber Danke
> Es gibt ein Add-In mit =DEZINBIN(). Aber soweit ich mich erinnere,
> macht das Probleme bei längeren Zahlen. Wenn Du ohnehin schon mit VBA
> arbeitest, kannst Du auch noch eine kleine rekursive Function dazunehmen.
>
> Peter
>
> MsgBox dec2bin(&H7F03)
> MsgBox Format(dec2bin(&H7F03), String(16, "0"))
>
> Function dec2bin(ByVal dez As Long) As String
> If dez > 0 Then dec2bin = dec2bin(dez \ 2) & dez Mod 2
> End Function
Ich hab es gestern ausprobiert und es funktioniert insoweit ganz gut,
nur durfte ich die Werte nicht als Integer sondern nur als Byte
verarbeiten, was am Ende auch einen Sinn ergibt weil beide Bytes
verschiedene Bereiche abdecken, die ich aber nur als einen gesehen habe.
Mit Integer kommen teilweise negative Zahlen raus die dann nur noch als
Null ausgegeben werden.
Was mit der Msgbox funktioniert, nämlich die Formatierung, will Excel
natürlich in sein eigenes Format drücken und das heißt erstmal führende
Nullen sind zu elemenieren. Ich habe aber einfach die Zellen
vorformatiert und es sieht nun gut aus.
Also nochmals Danke
Jens