PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Unix-Zeit in menschenlesbare Zeitdarstellung



BoGe-Ro
30.11.2010, 06:42
Hallo Forum,

Der Thread-Titel verrät eigentlich schon alles.
Ich habe eine Funktion, die die aktuelle Unix-Zeit ermittelt.
Auf diese Unix-Zeit addiere ich eine Anzahl von Sekunden und möchte den Zeitpunkt (Datum und Uhrzeit) in menschenlesbarer Form ausgeben.
Dies alles soll mit Bascom auf einem Atmega 128 stattfinden - wobei der Punkt Bascom eigentlich egal ist.

Der grundsätzliche Ansatz ist klar, mir geht es darum die Fehlersuche abzukürzen, da ich mir vorstelle, Dass eventuelle Fehler nur zu bestimmten Daten auftreten und so mit nicht sichergestellt wäre, ob wirklich alle ausgeschlossen sind.

Deshalb meine Frage, hat jemand bereits einen C- oder Bascom-Code welcher fehlerfrei eine Unix-Zeitangabe zurückrechnet?


mfG

BoGe-Ro

TobiKa
30.11.2010, 07:19
Wie wäre es wenn du erstmal deinen Ansatz postest und man dann zusammen weiter macht. Bis jetzt hört es sich stark nach "Kann das mal einer für mich machen" an.

BoGe-Ro
30.11.2010, 08:34
Hallo,

Nach "Kann das mal einer machen" sollte es nicht klingen - die Frage war mehr: "Hat es schon einer gemacht und ist zufrieden mit dem Ergebnis?".

Natürlich habe ich mir auch eine Lösung einfallen lassen - welche auch an den getesteten Zeitpunkten funktioniert - jedoch halte ich sie für ziemlich langsam, noch wurden alle Eventualitäten überprüft.

Nachfolgend meine Lösung, welche im Bascom-Simulator läuft:




$regfile = "m128def.dat"
$crystal = 16000000
$framesize = 120
$swstack = 120
$hwstack = 120
$baud = 57600
$sim

Dim Zeit_long As Long
Dim Zeit_string As String * 12

Declare Function Unixzeit(byval _tag As Byte , Byval _monat As Byte , _
Byval _jahr As Word , Byval _stunde As Byte , _
Byval _minute As Byte , Byval _sekunde As Byte) As Long

Declare Function Zeit(byval _unixzeit As Long) As String
Declare Function Schaltjahr(byval _jahr As Word) As Byte

Do
Zeit_long = Unixzeit(19 , 10 , 2010 , 13 , 35 , 00)
Print Space(12) ; "19.10.2010 13:35:00" ; Space(4);
Print "UnixZeit: " ; Zeit_long
Zeit_string = Zeit(zeit_long)
Print "Zeitstring: " ; Zeit_string


Zeit_long = Unixzeit(17 , 09 , 1976 , 11 , 11 , 11)
Print Space(12) ; "17.09.1976 11:11:11" ; Space(4);
Print "UnixZeit: " ; Zeit_long
Zeit_string = Zeit(zeit_long)
Print "Zeitstring: " ; Zeit_string


Zeit_long = Unixzeit(30 , 11 , 2010 , 09 , 10 , 30)
Print Space(12) ; "30.11.2010 09:10:30" ; Space(4);
Print "UnixZeit: " ; Zeit_long
Zeit_string = Zeit(zeit_long)
Print "Zeitstring: " ; Zeit_string

Loop
End


Function Unixzeit(byval _tag As Byte , Byval _monat As Byte , _
Byval _jahr As Word , Byval _stunde As Byte , _
Byval _minute As Byte , Byval _sekunde As Byte) As Long

'http://de.wikipedia.org/wiki/Unixzeit
Local _jahre As Byte
Local _schaltjahre As Single
Local _term1 As Single , _term2 As Single , _term3 As Single
Local _unix_zeit As Long
Local _help_long As Long
Local _help_byte As Byte
Local _help_b1 As Byte , _help_b2 As Byte , _help_b3 As Byte

_stunde = _stunde - 2 'Sommerzeit und UTC

_jahre = _jahr - 1970

_term1 = _jahr - 1
_term1 = _term1 - 1968
_term1 = _term1 / 4

_term2 = _jahr - 1
_term2 = _term2 - 1900
_term2 = _term2 / 100

_term3 = _jahr - 1
_term3 = _term3 - 1600
_term3 = _term3 / 400

_schaltjahre = _term1 - _term2
_schaltjahre = _schaltjahre + _term3
_schaltjahre = Int(_schaltjahre)

_unix_zeit = _sekunde

_help_long = 60 * _minute
_unix_zeit = _unix_zeit + _help_long

_help_long = 3600 * _stunde
_unix_zeit = _unix_zeit + _help_long

_help_byte = _monat - 1
_help_long = Lookup(_help_byte , Tage_bis_monatsanfang)
_help_long = _help_long + _tag
_help_long = _help_long - 1
_help_long = _help_long * 86400
_unix_zeit = _unix_zeit + _help_long

_help_byte = _schaltjahre
_help_long = _jahre * 365
_help_long = _help_long + _help_byte
_help_long = _help_long * 86400
_unix_zeit = _unix_zeit + _help_long

_help_b1 = _jahr Mod 4
_help_b2 = _jahr Mod 100
_help_b3 = _jahr Mod 400
If _help_b2 <> 0 Or _help_b3 = 0 Then If _help_b1 = 0 And _monat > 2 Then _unix_zeit = _unix_zeit + 86400

Unixzeit = _unix_zeit
End Function



Tage_bis_monatsanfang:
Data 0& , 31& , 59& , 90& , 120& , 151& , 181& , 212& , 243& , 273& , 304& , 334&


Function Zeit(byval _unixzeit As Long) As String
'Start: 01.01.1970 00:00 Uhr UTC
Local _dauer_tage As Long
Local _dauer_stunden As Long
Local _dauer_minuten As Long
Local _dauer_sekunden As Long
Local _tage As Byte
Local _monate As Byte
Local _jahre As Word
Local _help_word As Word
Local _help_byte As Byte
Local _anzahl_tage_im_monat As Byte
Local _ausgabestring As String * 30

_unixzeit = _unixzeit + 7200 'Korrektur auf Sommerzeit und UTC

_dauer_tage = _unixzeit \ 86400
_unixzeit = _unixzeit Mod 86400

_dauer_stunden = _unixzeit \ 3600
_unixzeit = _unixzeit Mod 3600

_dauer_minuten = _unixzeit \ 60
_dauer_sekunden = _unixzeit Mod 60

_jahre = 1970 'Startwert
_monate = 01 'Startwert
' _tage = 1
Do
_anzahl_tage_im_monat = Lookup(_monate , Monatslaenge)

_help_byte = Schaltjahr(_jahre)
If _monate = 2 And _help_byte = 1 Then _anzahl_tage_im_monat = 29

If _dauer_tage > _anzahl_tage_im_monat Then
Incr _monate
_dauer_tage = _dauer_tage - _anzahl_tage_im_monat
If _monate > 12 Then
Incr _jahre
_monate = _monate - 12
End If
End If
Loop Until _dauer_tage <= _anzahl_tage_im_monat

Incr _dauer_tage 'damits nicht am 00.01.1970 startet

_ausgabestring = Str(_dauer_tage) + "." + Str(_monate) + "." + Str(_jahre)
_ausgabestring = _ausgabestring + " " + Str(_dauer_stunden) + ":" + Str(_dauer_minuten) + ":" + Str(_dauer_sekunden)

Zeit = _ausgabestring
End Function


Monatslaenge:
Data 0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31



Function Schaltjahr(byval _jahr As Word) As Byte
Local _durch4 As Word
Local _durch100 As Word
Local _durch400 As Word
Local _schaltjahr As Byte : _schaltjahr = 0

_durch4 = _jahr Mod 4
_durch100 = _jahr Mod 100
_durch400 = _jahr Mod 400

If _durch4 = 0 Then _schaltjahr = 1
If _durch100 = 0 Then _schaltjahr = 0
If _durch400 = 0 Then _schaltjahr = 1

Schaltjahr = _schaltjahr
End Function

BoGe-Ro
30.11.2010, 09:04
obiger Code funtioniert zwar für die eingefügten Testdaten, allerdings schon nicht mehr, wenn man das morgige Datum zurückrechnen möchte.

Dies fiel mir eben in einem anderen Test auf - und zeigt mir, wie schwierig es ist, auch jeden Fall vorher abzuklopfen.

korrigiert sieht es nun so aus:



$regfile = "m128def.dat"
$crystal = 16000000
$framesize = 120
$swstack = 120
$hwstack = 120
$baud = 57600
$sim

Dim Zeit_long As Long
Dim Zeit_string As String * 12

Declare Function Unixzeit(byval _tag As Byte , Byval _monat As Byte , _
Byval _jahr As Word , Byval _stunde As Byte , _
Byval _minute As Byte , Byval _sekunde As Byte) As Long

Declare Function Zeit(byval _unixzeit As Long) As String
Declare Function Schaltjahr(byval _jahr As Word) As Byte

Do
Zeit_long = Unixzeit(30 , 11 , 2010 , 09 , 10 , 30)
Print Space(12) ; "30.11.2010 09:10:30" ; Space(4);
Print "UnixZeit: " ; Zeit_long

Zeit_long = Zeit_long + 86400 'einen Tag draufaddieren

Zeit_string = Zeit(zeit_long)
Print "Zeitstring: " ; Zeit_string

Loop
End


Function Unixzeit(byval _tag As Byte , Byval _monat As Byte , _
Byval _jahr As Word , Byval _stunde As Byte , _
Byval _minute As Byte , Byval _sekunde As Byte) As Long

'http://de.wikipedia.org/wiki/Unixzeit
Local _jahre As Byte
Local _schaltjahre As Single
Local _term1 As Single , _term2 As Single , _term3 As Single
Local _unix_zeit As Long
Local _help_long As Long
Local _help_byte As Byte
Local _help_b1 As Byte , _help_b2 As Byte , _help_b3 As Byte

_stunde = _stunde - 2 'Sommerzeit und UTC

_jahre = _jahr - 1970

_term1 = _jahr - 1
_term1 = _term1 - 1968
_term1 = _term1 / 4

_term2 = _jahr - 1
_term2 = _term2 - 1900
_term2 = _term2 / 100

_term3 = _jahr - 1
_term3 = _term3 - 1600
_term3 = _term3 / 400

_schaltjahre = _term1 - _term2
_schaltjahre = _schaltjahre + _term3
_schaltjahre = Int(_schaltjahre)

_unix_zeit = _sekunde

_help_long = 60 * _minute
_unix_zeit = _unix_zeit + _help_long

_help_long = 3600 * _stunde
_unix_zeit = _unix_zeit + _help_long

_help_byte = _monat - 1
_help_long = Lookup(_help_byte , Tage_bis_monatsanfang)
_help_long = _help_long + _tag
_help_long = _help_long - 1
_help_long = _help_long * 86400
_unix_zeit = _unix_zeit + _help_long

_help_byte = _schaltjahre
_help_long = _jahre * 365
_help_long = _help_long + _help_byte
_help_long = _help_long * 86400
_unix_zeit = _unix_zeit + _help_long

_help_b1 = _jahr Mod 4
_help_b2 = _jahr Mod 100
_help_b3 = _jahr Mod 400
If _help_b2 <> 0 Or _help_b3 = 0 Then If _help_b1 = 0 And _monat > 2 Then _unix_zeit = _unix_zeit + 86400

Unixzeit = _unix_zeit
End Function



Tage_bis_monatsanfang:
Data 0& , 31& , 59& , 90& , 120& , 151& , 181& , 212& , 243& , 273& , 304& , 334&


Function Zeit(byval _unixzeit As Long) As String
'Start: 01.01.1970 00:00 Uhr UTC
Local _dauer_tage As Long
Local _dauer_stunden As Long
Local _dauer_minuten As Long
Local _dauer_sekunden As Long
Local _tage As Byte
Local _monate As Byte
Local _jahre As Word
Local _help_word As Word
Local _help_byte As Byte
Local _anzahl_tage_im_monat As Byte
Local _ausgabestring As String * 30

_unixzeit = _unixzeit + 7200 'Korrektur auf Sommerzeit und UTC

_dauer_tage = _unixzeit \ 86400
_unixzeit = _unixzeit Mod 86400

_dauer_stunden = _unixzeit \ 3600
_unixzeit = _unixzeit Mod 3600

_dauer_minuten = _unixzeit \ 60
_dauer_sekunden = _unixzeit Mod 60

_jahre = 1970 'Startwert
_monate = 01 'Startwert

Incr _dauer_tage 'damits nicht am 00.01.1970 startet

Do
_anzahl_tage_im_monat = Lookup(_monate , Monatslaenge)

If _monate = 2 Then
_help_byte = Schaltjahr(_jahre)
If _help_byte = 1 Then _anzahl_tage_im_monat = 29
End If

If _dauer_tage > _anzahl_tage_im_monat Then
Incr _monate
_dauer_tage = _dauer_tage - _anzahl_tage_im_monat
If _monate > 12 Then
Incr _jahre
_monate = _monate - 12
End If
End If
_anzahl_tage_im_monat = Lookup(_monate , Monatslaenge)
Loop Until _dauer_tage <= _anzahl_tage_im_monat

_ausgabestring = Str(_dauer_tage) + "." + Str(_monate) + "." + Str(_jahre)
_ausgabestring = _ausgabestring + " " + Str(_dauer_stunden) + ":" + Str(_dauer_minuten) + ":" + Str(_dauer_sekunden)

Zeit = _ausgabestring
End Function


Monatslaenge:
Data 0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31



Function Schaltjahr(byval _jahr As Word) As Byte
Local _durch4 As Word
Local _durch100 As Word
Local _durch400 As Word
Local _schaltjahr As Byte : _schaltjahr = 0

_durch4 = _jahr Mod 4
_durch100 = _jahr Mod 100
_durch400 = _jahr Mod 400

If _durch4 = 0 Then _schaltjahr = 1
If _durch100 = 0 Then _schaltjahr = 0
If _durch400 = 0 Then _schaltjahr = 1

Schaltjahr = _schaltjahr
End Function

BoGe-Ro
02.12.2010, 09:43
Hallo Forum,

ich muss mein Rechenproblem mal etwas aufsplitten - denn ich hab bemerkt, dass meine Bascom-Umsetzung des Algorithmus auf http://de.wikipedia.org/wiki/Unixtime nicht perfekt funktioniert.

Zum Testen habe ich nachfolgenden Code auf einen ATMega geladen und die Ausgaben im Terminal mitgeschrieben und per Excel verglichen.

Resultat: es werden alle Daten seit 01.01.1970 an die Funtion zur Umrechnung in den Zeitstempel gegeben (der Einfachheit halber jeweils zur Uhrzeit 00:00:00) und das Ergebnis mit einer Variablen deren Wert sich bei jedem Durchlauf um 86400 (24 Stunden) erhöht verglichen.

Folgendes läßt sich feststellen:

- im Zeitraum 01.01.1970 - 31.12.2004 sind die Ergebnisse korrekt
- im Zeitraum 01.01.2005 - 31.12.2036 stimmt das Folgejahr nach einem Schaltjahr nicht (1 Tage Differenz)
- im Zeitraum 01.01.2037 - ... sind die 2 auf das Schaltjahre folgenden Jahre um 1 Tag verschoben.

Es wurde keinerlei Korrektur vorgenommen - die stimmenden Jahre dazwischen haben sich durch den selben Programmcode ergeben.

wer kann den Fehler finden?



$regfile = "m16def.dat"
$crystal = 8000000
$framesize = 120
$swstack = 120
$hwstack = 120
$baud = 57600
'$sim

Dim Zeit_long As Long
Dim Zeit_inkr As Long : Zeit_inkr = 0
Dim Differenz As Single

Dim Tag As Byte : Tag = 01
Dim Monat As Byte : Monat = 01
Dim Jahr As Word : Jahr = 1970
Dim Stunde As Byte : Stunde = 00
Dim Minute As Byte : Minute = 00
Dim Sekunde As Byte : Sekunde = 00
Dim Help_byte As Byte


Declare Function Unixzeit(byval _tag As Byte , Byval _monat As Byte , _
Byval _jahr As Word , Byval _stunde As Byte , _
Byval _minute As Byte , Byval _sekunde As Byte) As Long

Declare Function Schaltjahr(byval _jahr As Word) As Byte

Wait 10

Zeit_long = Unixzeit(31 , 12 , 2004 , 0 , 0 , 0)
Print "31.12.2004 = " ; Zeit_long

Zeit_long = Unixzeit(1 , 1 , 2005 , 0 , 0 , 0)
Print "01.01.2005 = " ; Zeit_long


Do
Print Tag ; "." ; Monat ; "." ; Jahr ; Chr(9) ; Stunde ; ":" ; Minute ; ":" ; Sekunde ; Chr(9);
Zeit_long = Unixzeit(tag , Monat , Jahr , Stunde , Minute , Sekunde)

Differenz = Zeit_long - Zeit_inkr

If Differenz <> 0 Then
Print "Fehler: " ; Tag ; "." ; Monat ; "." ; Jahr ; " Differenz : " ; Differenz ; " Sek = ";
Differenz = Differenz / 86400
Print Differenz ; " Tage";
'Wait 5
End If
Print

Incr Tag
Zeit_inkr = Zeit_inkr + 86400

Help_byte = Lookup(monat , Monatslaenge)
If Monat = 2 Then
Help_byte = Schaltjahr(jahr)
If Help_byte = 1 Then Help_byte = 29 Else Help_byte = 28
End If
If Tag > Help_byte Then
Tag = 1
Incr Monat
If Monat > 12 Then
Monat = 1
Incr Jahr
End If
End If
Loop
End


Function Unixzeit(byval _tag As Byte , Byval _monat As Byte , _
Byval _jahr As Word , Byval _stunde As Byte , _
Byval _minute As Byte , Byval _sekunde As Byte) As Long

'http://de.wikipedia.org/wiki/Unixzeit
Local _jahre As Byte
Local _schaltjahre As Single
Local _term1 As Single , _term2 As Single , _term3 As Single
Local _unix_zeit As Long
Local _help_long As Long
Local _help_byte As Byte
Local _help_b1 As Byte , _help_b2 As Byte , _help_b3 As Byte

_jahre = _jahr - 1970

_term1 = _jahr - 1
_term1 = _term1 - 1968
_term1 = _term1 / 4

_term2 = _jahr - 1
_term2 = _term2 - 1900
_term2 = _term2 / 100

_term3 = _jahr - 1
_term3 = _term3 - 1600
_term3 = _term3 / 400

_schaltjahre = _term1 - _term2
_schaltjahre = _schaltjahre + _term3
_schaltjahre = Int(_schaltjahre)

_unix_zeit = _sekunde

_help_long = 60 * _minute
_unix_zeit = _unix_zeit + _help_long

_help_long = 3600 * _stunde
_unix_zeit = _unix_zeit + _help_long

_help_byte = _monat - 1
_help_long = Lookup(_help_byte , Tage_bis_monatsanfang)
_help_long = _help_long + _tag
_help_long = _help_long - 1
_help_long = _help_long * 86400
_unix_zeit = _unix_zeit + _help_long

_help_byte = _schaltjahre
_help_long = _jahre * 365
_help_long = _help_long + _help_byte
_help_long = _help_long * 86400
_unix_zeit = _unix_zeit + _help_long

If _monat > 2 Then
_help_byte = Schaltjahr(_jahr)
If _help_byte = 1 Then _unix_zeit = _unix_zeit + 86400
End If

Unixzeit = _unix_zeit
End Function



Tage_bis_monatsanfang:
Data 0& , 31& , 59& , 90& , 120& , 151& , 181& , 212& , 243& , 273& , 304& , 334&

Monatslaenge:
Data 0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31


Function Schaltjahr(byval _jahr As Word) As Byte
Local _durch4 As Word
Local _durch100 As Word
Local _durch400 As Word
Local _schaltjahr As Byte : _schaltjahr = 0

_durch4 = _jahr Mod 4
If _durch4 = 0 Then
_schaltjahr = 1
_durch100 = _jahr Mod 100
_durch400 = _jahr Mod 400
If _durch100 = 0 Then _schaltjahr = 0
If _durch400 = 0 Then _schaltjahr = 1
Else
_schaltjahr = 0
End If

Schaltjahr = _schaltjahr
End Function




Besten Dank

BoGe-Ro