- LiFePO4 Speicher Test         
Ergebnis 1 bis 5 von 5

Thema: Unix-Zeit in menschenlesbare Zeitdarstellung

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67

    Unix-Zeit in menschenlesbare Zeitdarstellung

    Anzeige

    Praxistest und DIY Projekte
    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

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.04.2010
    Beiträge
    1.249
    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.

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67
    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:

    Code:
    $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

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67
    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:

    Code:
    $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

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    19.02.2010
    Beiträge
    67

    Teilschritt Unix-Zeitstempel berechnen

    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?

    Code:
    $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

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress