Datediff - Stunden - Zeitumstellung

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von runatthesun.

    Datediff - Stunden - Zeitumstellung

    Hallo Zusammen,

    ich habe ein Paar Probleme mit den Datumsfunktionen und der Zeitumstellung.

    Ich habe Zeitreihen die UTC-kodiert sind. Bei der Berechnung von datums differenzen bzw. beim "addieren" von Stunden scheinen die Funktionen datediff/dateadd (manchmal) die Zeitumstellung zu ignorieren.

    Weise ich bspw. über Cdate einer Datumsvariable einen UTC-String zu, so wird die Zeit korrekt dargestellt. die Stundendifferenz hingegen wird über datediff falsch ausgegeben, berechne ich sie über (date).toBinary stimmt sie hingegen.
    Ein ähnliches Problem gibt es bei der dateadd-funktion. Weise ich hier dem Datum einen UTC-String zu, so liefer dateadd falsche werte. weise ich hingegen einen "deutschen" string zu, läuft dateadd richtig, der Zeitstempel ist jedoch um eine Stunde versetzt.

    Hat nun jemand einen Tipp für mich, wie sich Probleme mit den Zeitstempeln grundsätzlich vermeiden lassen, bzw. eine Erklärung für die für mich komische Art zu "rechnen"?

    Vielen Dank.

    RatS


    Nachfolgender Code illustiert, quick and dirty, die problematik.


    Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Dim dattemp As Date, datstart As Date, datAddTmpUTC As Date, datAddtmp As Date
    4. Dim strtemp() As String = {"2012-03-25T00:00:00+01:00", "2012-03-25T01:00:00+01:00", "2012-03-25T03:00:00+02:00", "2012-03-25T04:00:00+02:00", "2012-03-25T05:00:00+02:00", "2012-03-25T06:00:00+02:00", "2012-03-25T07:00:00+02:00", "2012-03-25T08:00:00+02:00", "2012-03-25T09:00:00+02:00", "2012-03-25T10:00:00+02:00", "2012-03-25T11:00:00+02:00"}
    5. Dim i As Integer, l As Long, k As Long
    6. datstart = CDate(strtemp(0))
    7. k = datstart.ToBinary
    8. datAddTmpUTC = CDate("2012-03-25T00:00+01:00")
    9. datAddtmp = CDate("25.03.2012 00:00")
    10. Me.Label1.Text = "UTC as String - Date of Str .tolocalTime - dateadd hour .tolocaltime - dateaddUTC hour .tolocaltime - diffBinary - Datediff" & vbCrLf
    11. For i = 0 To UBound(strtemp)
    12. dattemp = CDate(strtemp(i))
    13. l = dattemp.ToBinary
    14. Me.Label1.Text &= strtemp(i) & "___" & dattemp.ToLocalTime & "___" & datAddtmp.ToLocalTime & "___" & datAddTmpUTC.ToLocalTime & "___" & (l - k) / 36000000000 & "___" & DateDiff(DateInterval.Hour, datstart, dattemp) & vbCrLf
    15. datAddtmp = DateAdd(DateInterval.Hour, 1, datAddtmp)
    16. datAddTmpUTC = DateAdd(DateInterval.Hour, 1, datAddTmpUTC)
    17. Next
    18. End Sub
    19. End Class


    Schau dir mal TimeSpan an. Das ist "schöner" als DateDiff.
    There is no CLOUD - just other people's computers

    Q: Why do JAVA developers wear glasses?
    A: Because they can't C#

    Daily prayer:
    "Dear Lord, grand me the strength not to kill any stupid people today and please grant me the ability to punch them in the face over standard TCP/IP."
    Willkommen im Forum. :thumbup:

    runatthesun schrieb:

    Ich habe Zeitreihen die UTC-kodiert sind.
    Dann lies sie als genau dies ein:

    VB.NET-Quellcode

    1. Dim dt As New DateTime(2014, 7, 1, 12, 0, 0, DateTimeKind.Utc)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    runatthesun schrieb:

    liefert den gleichen Fehler:
    Mit welchem Input?

    RodFromGermany schrieb:

    VB.NET-Quellcode

    1. Dim dt As New DateTime(2014, 7, 1, 12, 0, 0, DateTimeKind.Utc)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    konnte gestern leider nicht mehr anworten.

    Das Problem taucht auf, wenn ich die "orginal" Zeitstempel der Form YYYY-MM-ddThh:mm:ss+01:00 bzw. +02:00 über Cdate einer datumsvariablen zuweise.
    Die Zuweisung erfolgt korrekt, die ausgabe liefert die "richtige" Zeit. Die Berechnug über datediff oder auch intervall hingegen erzeugt die falsche Differenz, die berechnung über tobinary die richtige.

    Zum Einlesen:
    Im Ganzen verfolge ich das Ziel, Zeitreihen zu modellieren. Dabei sind ein Teil der Daten Messwerte, die nach eben diesem Muster kodiert sind und es auch bleiben sollten, um sowohl das grds. Problem der Fehl- bzw. Doppelstunde zu umgehen als auch den kalendarischen Bezug zu erhalten. Also der 1.1. 00:00 soll der 1.1. 00:00 bleiben und nicht zum UTC: 31.12. 23:00 werden.

    Ich denke ich werde einfach die Berechnung über die Binärwerte machen um das problem zu umgehen.

    Vielen Dank.
    Was ist der Unterschied zwischen

    runatthesun schrieb:

    Cdat
    und

    RodFromGermany schrieb:

    VB.NET-Quellcode

    1. New DateTime
    :?:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also nach ein wenig rumprobieren steige ich so langsam durch......

    Es gibt wohl zwei unterschiedliche "Arten" wie die nach aussen gleiche Daten gespeichert werden.

    Eine Zuweisung von
    CDate("2012-03-25T03:00:00+02:00") an eine datumsvariable liefert den gleichen Binary-Wert wie die Zuweisung über
    New DateTime(2012, 3, 25, 3, 0, 0, DateTimeKind.Local) (-8588689696854775808)

    Eine zuweisung von CDate("2012-03-25T03:00:00") liefert den gleichen wert wie CDate("25.03.2012 03:00") (634682412000000000)

    Die binärwerte untereinander sind jedoch nicht "kompatibel".

    Das wieso und warum erschliesst sich mir zwar nicht, ich bin auch alles andere als ein Profi, aber ich werde wohl stets eine "Art" erzwingen müssen.

    Gruß

    runatthesun schrieb:

    steige ich so langsam durch
    Du bekommst einen richtigen Tipp, wie Du UTC-Zeit-Objekte erstellen kannst und ignorierst sie.
    Offensichtlich hast Du keine weiteren Probleme. X(
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Zum Verständnis:

    ich habe den Tipp nicht ignoriert, sondern genutzt.

    Das Problem ist, dass das Programm auch von (einigen wenigen) Kollegen genutzt werden soll.
    Im derzeitigen Stadium werden die Messwerte noch über .csv Dateien eingelesen.
    Lesen diese nun Messdaten ein bzw. legen welche an führen Abweichungen in der Datumskodierung des Strings, welche grds. die gleiche Information enthalten u.U. zu Fehlern die nicht nicht bemerkt werden, da Datum (wohl) nicht gleich Datum ist.
    Daher hätte ich es schick gefunden, wenn man jegliche "Datum strings" in eine Datumsvariable konvertieren kann die untereinander kompatibel sind, was aber wohl so einfach nicht geht, bzw. nur mit einem extra parser.

    Falls ich ignorant rübergekommen sein sollte, so sei es mir bitte verziehen :)
    Guck dir das mal an:
    Spoiler anzeigen

    C#-Quellcode

    1. namespace ConsoleApplication
    2. {
    3. class Program
    4. {
    5. static void Main(string[] args)
    6. {
    7. DateTime dt1 = DateTime.Parse("2012-03-25T00:00:00");
    8. DateTime dt2 = new DateTime(2012, 3, 25, 3, 0, 0);
    9. DateTimeOffset dto1 = new DateTimeOffset(dt1, new TimeSpan(1, 0, 0));
    10. DateTimeOffset dto2 = new DateTimeOffset(dt2, new TimeSpan(2, 0, 0));
    11. Console.WriteLine("DT1: " + dt1.ToString());
    12. Console.WriteLine("DT2: " + dt2.ToString());
    13. Console.WriteLine("DT1 mit UTC Offset: " + dto1.ToString());
    14. Console.WriteLine("DT2 mit UTC Offset: " + dto2.ToString());
    15. Console.WriteLine("Differenz: " + (dto2 - dto1).ToString());
    16. Console.ReadLine();
    17. }
    18. }
    19. }
    Bilder
    • UTC Problem.JPG

      153,56 kB, 1.366×768, 192 mal angesehen
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais

    runatthesun schrieb:

    Daher hätte ich es schick gefunden,
    mich mal grundsätzlich mit der DateTime-Struktur zu befassen und zu lernen, wie ich damit meine Probleme lösen kann.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ich bin noch am lernen und da noch einen riesen berg vor mir. Bitte übt Nachsicht.

    Habe mir Rods Rat zu Herzen genommen und das Problem gelöst.

    Dem Parser müssen zusätzliche Parameter übergeben werden. Sieht er so aus:

    .Parse(tmpdatum, Nothing, Globalization.DateTimeStyles.AdjustToUniversal)

    Funktionierts auch mit regionalisierten UTC-Zeitstempeln.

    Für Rat und Nerven

    vielen Dank.

    gruß
    @theplexian:
    Um Ehrlich zu sein, war er für mich nicht praktikabel, aber inspirirend :) Danke.
    Gelöst habe ich es wie im Spoiler

    Spoiler anzeigen

    Quellcode

    1. Shared Function fctIndexofDate(tmpdatum As String, startJahr As Integer) As Integer
    2. Dim i As TimeSpan
    3. Dim datStart As New DateTime(startJahr - 1, 12, 31, 23, 0, 0, 0, DateTimeKind.Utc)
    4. Dim dtTemp As New DateTime
    5. dtTemp = DateTime.Parse(tmpdatum, Nothing, Globalization.DateTimeStyles.AdjustToUniversal)
    6. i = dtTemp - datStart
    7. fctIndexofDate = i.TotalHours