Fortgeschrittene Arbeit mit Datum und Uhrzeit in C#: von der Theorie zu realen Aufgaben
Die Arbeit mit Datum und Uhrzeit gehört zu den häufigsten und gleichzeitig tückischsten Aufgaben in der Entwicklung. Auf Anfängerniveau erstellen wir einfach DateTime.Now und geben es in der Konsole aus. Aber wenn ein Projekt über den spielerischen Rahmen hinauswächst, tauchen Komplexitäten auf: Sommerzeitumstellung, verschiedene Zeitzonen, hohe Rechengenauigkeit oder die Notwendigkeit, mit Datumsangaben ohne Zeitzone zu arbeiten. In diesem Artikel behandeln wir fortgeschrittene Techniken für die Arbeit mit Datum und Uhrzeit in C# (.NET), die Ihnen helfen, zuverlässigen und vorhersagbaren Code zu schreiben.
1. DateTime, DateTimeOffset und TimeSpan: das richtige Werkzeug auswählen
Viele Entwickler verwenden standardmäßig DateTime, ohne über dessen Einschränkungen nachzudenken. Auf fortgeschrittenem Niveau ist es wichtig, den Unterschied zwischen den drei grundlegenden Typen zu verstehen.
DateTime
Speichert Datum und Uhrzeit. Sein Hauptproblem ist die Mehrdeutigkeit. Die Eigenschaft Kind (Local, Utc, Unspecified) wird nicht immer explizit gesetzt, was zu Fehlern bei der Serialisierung oder beim Vergleich führt.
DateTimeOffset
Speichert Datum, Uhrzeit und den Offset zur UTC. Dies ist der empfohlene Typ zum Speichern von Zeitpunkten, da er einen Punkt auf der Zeitachse eindeutig bestimmt. Beispielsweise ist 2025-03-15T14:00:00+03:00 immer ein bestimmter Moment, unabhängig von der Zeitzone des Benutzers.
TimeSpan
Stellt ein Zeitintervall dar, keinen bestimmten Zeitpunkt. Wird für Arithmetik verwendet: Differenz zwischen Daten, Timeouts, Dauer von Operationen.
// Beispiel: DateTime vs DateTimeOffsetDateTime localNow = DateTime.Now; // Kind = LocalDateTime utcNow = DateTime.UtcNow; // Kind = Utc
DateTimeOffset preciseNow = DateTimeOffset.Now; // Immer mit Angabe des Offsets
// Vergleich: DateTimeOffset ist eindeutigerConsole.WriteLine(preciseNow.Offset); // +03:00 oder -05:00 usw.Tipp: Verwenden Sie für neue Projekte DateTimeOffset zum Speichern von Zeitpunkten, TimeSpan für Intervalle und DateTime nur, wenn es wirklich notwendig ist (z. B. für Kompatibilität mit altem Code).
2. Parsing und Formatierung: Wie man keine FormatException bekommt
Das Parsen von Daten aus Zeichenfolgen ist eine häufige Fehlerquelle, insbesondere wenn die Zeichenfolgen von Benutzern oder aus verschiedenen Kulturen stammen.
Kulturabhängiges Parsing
Verwenden Sie CultureInfo.InvariantCulture für den internen Datenaustausch (z. B. JSON, API). Für Benutzereingaben berücksichtigen Sie die Kultur des Benutzers.
// Parsing unter Berücksichtigung der Kulturstring dateString = "15.03.2025";var ruCulture = new CultureInfo("ru-RU");DateTime parsedDate = DateTime.Parse(dateString, ruCulture);
// Invariantes Parsing (für API empfohlen)string isoString = "2025-03-15T14:00:00Z";DateTimeOffset parsedIso = DateTimeOffset.Parse(isoString, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);TryParseExact für Zuverlässigkeit
Wenn das Format der Zeichenfolge bekannt ist, verwenden Sie TryParseExact mit expliziter Angabe des Formats. Dies schließt unerwartete Ausnahmen aus.
string input = "2025-03-15 14:30";string format = "yyyy-MM-dd HH:mm";if (DateTime.TryParseExact(input, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)){ Console.WriteLine($"Erfolgreich: {result}");}else{ Console.WriteLine("Parsing-Fehler");}Benutzerdefinierte Formatierung
Die Standardspezifizierer (d, D, t, T) sind gut, aber für präzise Kontrolle verwenden Sie benutzerdefinierte Formatzeichenfolgen.
DateTime now = DateTime.Now;Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm:ss.fff")); // 2025-03-15 14:30:45.123Console.WriteLine(now.ToString("dd MMMM yyyy, dddd")); // 15 März 2025, Samstag