CodeGym /Kurse /C# SELF /Formatierung und Parsen von Daten und Uhrzeiten

Formatierung und Parsen von Daten und Uhrzeiten

C# SELF
Level 15 , Lektion 3
Verfügbar

1. Formatierung von Daten

Wenn du denkst, dass die Ausgabe 2025-06-19T17:30:00 ziemlich cool aussieht, dann zeig dieses Format mal deiner Oma oder einem Buchhalter. Wahrscheinlich bevorzugen sie etwas Einfacheres: 19.06.2025 17:30. Deine englischsprachigen Kollegen erwarten 06/19/2025 5:30 PM. DevOps und Maschinen stehen sowieso auf 2025-06-19T17:30:00Z. Also kann ein DateTime im Speicher zig verschiedene Formate auf dem Bildschirm haben.

Das Gegenteil ist auch ein Klassiker: Der User gibt ein Datum ins Eingabefeld ein ("19.06.2025"), und wir müssen es in ein C#-Objekt umwandeln und dürfen nicht durcheinanderkommen, was Tag und was Monat ist. Automatisierung, Integrationen, Reports – überall ist die richtige Interpretation von Textdaten wichtig.

Basis-Formatierung

In C# kannst du ein Datums-/Zeitobjekt (DateTime, DateOnly, TimeOnly, DateTimeOffset) mit der Methode .ToString() in einen String umwandeln:


DateTime now = DateTime.Now;
Console.WriteLine(now.ToString()); // Ausgabe: 19.06.2025 17:30:25
Basis-Formatierung von Datum und Uhrzeit

Wenn du .ToString() ohne Parameter aufrufst, wird das Format der aktuellen Systemkultur verwendet (zum Beispiel zeigt ein deutsches Windows ein anderes Format als ein amerikanisches).

Standard-Formatstrings

Du kannst das Ausgabeformat explizit angeben, indem du sogenannte Standard-Formatstrings für Datum und Zeit verwendest:

Format Beschreibung Beispielausgabe
"d"
Kurzes Datum 19.06.2025
"D"
Vollständiges Datum 19. Juni 2025
"f"
Vollständiges Datum + kurze Zeit 19. Juni 2025 17:30
"F"
Vollständiges Datum + vollständige Zeit 19. Juni 2025 17:30:25
"g"
Kurzes Datum und Zeit 19.06.2025 17:30
"G"
Kurzes Datum + vollständige Zeit 19.06.2025 17:30:25
"t"
Kurze Zeit 17:30
"T"
Vollständige Zeit 17:30:25
"M"/"m"
Monat und Tag 19. Juni
"Y"/"y"
Jahr und Monat Juni 2025
"O"/"o"
ISO 8601 (Round-Trip) 2025-06-19T17:30:25.0000000

Console.WriteLine(now.ToString("d")); // 19.06.2025
Console.WriteLine(now.ToString("F")); // 19. Juni 2025 17:30:25
Console.WriteLine(now.ToString("O")); // 2025-06-19T17:30:25.0000000

Custom (benutzerdefinierte) Muster

Wenn du speziellere Formate brauchst, kannst du eigene Muster verwenden:

Symbol Bedeutung
yyyy Jahr, 4 Ziffern
yy Jahr, 2 Ziffern
MM Monat, 2 Ziffern
MMMM Monatsname
dd Tag, 2 Ziffern
d Tag, 1-2 Ziffern
HH Stunde (24h)
mm Minuten
ss Sekunden
tt AM/PM

Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm")); // 2025-06-19 17:30
Console.WriteLine(now.ToString("dd.MM.yyyy"));       // 19.06.2025
Console.WriteLine(now.ToString("dddd, MMMM d"));     // Mittwoch, Juni 19

Kulturelle Unterschiede beim Formatieren

Wenn du das Ergebnis im Stil eines anderen Landes oder einer anderen Sprache haben willst, nutze die Überladung ToString(string, IFormatProvider):


var enUS = new System.Globalization.CultureInfo("en-US");
Console.WriteLine(now.ToString("D", enUS)); // June 19, 2025
  • Wenn du ein festes Muster wie "MM/dd/yyyy" angibst, bekommst du unabhängig von der Kultur immer "06/19/2025".
  • Aber wenn du nur "d" oder "D" verwendest, hängt das Format von der Kultur ab!

Wichtige Punkte bei der Formatierung

Beim Arbeiten mit Datumsformaten ist es wichtig, den Unterschied zwischen Standard- und Custom-Formaten zu verstehen. Standardformate (wie "d", "F", "G") passen sich automatisch an die Systemkultur an, was für User-Interfaces praktisch ist, aber beim Datenaustausch zwischen Systemen zu Problemen führen kann. Custom-Formate geben dir volle Kontrolle über die Ausgabe, brauchen aber mehr Feintuning.

Besonders wichtig ist das Format "O" (oder "o") – das ist das sogenannte "Round-Trip"-Format, das garantiert, dass ein Datum, das in einen String und zurück umgewandelt wird, exakt gleich bleibt. Dieses Format ist besonders wichtig beim Serialisieren von Daten oder beim Übertragen übers Netzwerk.

2. Parsen von Daten und Uhrzeiten: Wie man aus einem String ein Objekt bekommt

Einfachstes Parsen: DateTime.Parse

DateTime.Parse ist eine Methode, die versucht, einen Datumsstring unter Berücksichtigung der Systemkultur zu erkennen.


string input = "19.06.2025";
DateTime parsed = DateTime.Parse(input);
Console.WriteLine(parsed); // 19.06.2025 00:00:00

Wenn der String ungültig ist, crasht das Programm mit einer Exception (niemand ist davor sicher!).

Kultur angeben


string input = "06/19/2025";
var enUS = new System.Globalization.CultureInfo("en-US");
DateTime dt = DateTime.Parse(input, enUS);
Console.WriteLine(dt); // 19.06.2025 00:00:00

Sicheres Parsen: TryParse


string input = "falsches datum";
bool ok = DateTime.TryParse(input, out DateTime safeDate);
if (!ok)
    Console.WriteLine("Fehler: Datum konnte nicht erkannt werden!");

Striktes Format angeben: ParseExact und TryParseExact


var culture = System.Globalization.CultureInfo.InvariantCulture;
string dateStr = "2025-06-19";

DateTime d = DateTime.ParseExact(dateStr, "yyyy-MM-dd", culture);
Console.WriteLine(d); // 19.06.2025 00:00:00

bool parsedOk = DateTime.TryParseExact(
    "19.06.2025",
    "dd.MM.yyyy",
    System.Globalization.CultureInfo.InvariantCulture,
    System.Globalization.DateTimeStyles.None,
    out DateTime myDate);

Tabelle beliebter Formate

String Format Endobjekt
"2025-06-19" "yyyy-MM-dd" 19. Juni 2025
"19.06.2025" "dd.MM.yyyy" 19. Juni 2025
"06/19/2025" "MM/dd/yyyy" 19. Juni 2025
"2025-06-19T14:15:16" "s" 19. Juni 2025 14:15:16

Arbeiten mit DateTimeStyles

Beim Parsen kannst du das Verhalten zusätzlich über den Parameter DateTimeStyles steuern. Dieses Enum erlaubt es dir, einzustellen, wie der Parser die Eingabedaten interpretieren soll. Zum Beispiel sorgt DateTimeStyles.AssumeUniversal dafür, dass die Zeit als UTC angenommen wird, wenn kein Offset angegeben ist. DateTimeStyles.AllowWhiteSpaces erlaubt es, überflüssige Leerzeichen im String zu ignorieren. Diese Einstellungen sind besonders praktisch, wenn du mit Daten aus externen Quellen arbeitest, bei denen das Format nicht immer vorhersehbar ist.

3. Formatierung und Parsen von DateOnly, TimeOnly

Die neuen Typen DateOnly und TimeOnly werden jetzt oft verwendet, um Daten/Zeit ohne unnötige Details zu speichern.

Formatierung


DateOnly birthday = new DateOnly(2000, 6, 19);
Console.WriteLine(birthday.ToString("dd MMMM yyyy")); // 19. Juni 2000

Parsen


var d = DateOnly.ParseExact("19.06.2000", "dd.MM.yyyy");
Console.WriteLine(d.Day); // 19

Genauso funktionieren die Methoden für TimeOnly (nur dass die Muster sich auf Stunden/Minuten/Sekunden beziehen):

TimeOnly t = TimeOnly.ParseExact("23:59", "HH:mm");
Console.WriteLine(t.Hour); // 23

Vorteile von DateOnly und TimeOnly

Die Verwendung von DateOnly und TimeOnly statt DateTime bringt einige wichtige Vorteile. Erstens ist es semantisch klarer – wenn du nur ein Datum ohne Zeit brauchst (z.B. Geburtsdatum), zeigt DateOnly diese Absicht deutlich. Zweitens hilft es, Probleme mit Zeitzonen zu vermeiden, die bei DateTime auftreten können. Drittens brauchen diese Typen weniger Speicherplatz in RAM und Datenbanken.

Formatierung und Parsen mit Zeitzonen

Wenn du Zeiten mit Offset speichern willst, nutze DateTimeOffset. Das ist besonders wichtig für internationale, verteilte Systeme. Alle Formatierungs- und Parse-Methoden funktionieren genauso, nur dass du jetzt auch das Offset steuern kannst:


DateTimeOffset meeting = new DateTimeOffset(2025, 6, 19, 17, 30, 0, TimeSpan.FromHours(3));
Console.WriteLine(meeting.ToString("o")); // 2025-06-19T17:30:00.0000000+03:00

string input = "2025-06-19T17:30:00+03:00";
var parsedOffset = DateTimeOffset.Parse(input);
Console.WriteLine(parsedOffset.Offset); // 03:00:00

4. Praktische Hinweise und typische Fehler

Eine der Fallen ist, beim Parsen internationaler Formate "Tag" und "Monat" zu verwechseln. Zum Beispiel ist der String "01/02/2025" in den USA der 2. Januar, in den meisten europäischen Ländern aber der 1. Februar (Überraschung!).

Oft wird auch vergessen, wie stark die Kultur Einfluss nimmt: Wenn die App auf einem Server in Deutschland läuft, aber User aus verschiedenen Ländern kommen, kann das Datumsformat aus der Datenbank auf jedem Server anders interpretiert werden.

Ein häufiger Fehler ist, .ToString() ohne Angabe von Kultur/Format für Logs und Datenaustausch zu verwenden: Das Ergebnis kann sich nach einer Migration auf ein anderes OS oder bei verschiedenen Windows-Usern ändern.

Tipps für die Arbeit mit Daten

  • Für interne Speicherung und Datenaustausch immer die Invariant Culture (CultureInfo.InvariantCulture) oder explizit angegebene Formate verwenden.
  • Für User-Interfaces die Kultur des Users nutzen oder ihm die Wahl des bevorzugten Formats lassen.
  • Bei API- und Datenbankarbeit immer ISO 8601-Format bevorzugen, das ist internationaler Standard.
  • Eingabedaten immer validieren: Existenz des Datums, Bereich und Plausibilität prüfen.

Arbeiten mit verschiedenen Datenquellen

Bei der Integration mit externen Systemen musst du oft mit Daten in verschiedenen Formaten arbeiten. Manche Systeme liefern Daten als Unix-Timestamp (Sekunden seit dem 1. Januar 1970), andere als Strings in nationalen Formaten. Es ist wichtig, sich vorher auf ein Austauschformat zu einigen und immer die Korrektheit des Parsings zu prüfen.

Außerdem solltest du daran denken, dass manche Formate mehrdeutig sein können. Zum Beispiel wird "12/13/2025" eindeutig als 13. Dezember 2025 interpretiert, aber "12/11/2025" kann je nach Kultur entweder der 12. November oder der 11. Dezember sein. In solchen Fällen ist es besser, weniger mehrdeutige Formate zu verwenden oder die Parsing-Kultur explizit anzugeben.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION