Menu

C# DateTime formatieren: Standard- und benutzerdefinierte Formatstrings, Kultur, ISO 8601

Wie du in C# einen DateTime als String formatierst: die Standardformatstrings (d, D, o, s, u, t), benutzerdefinierte Muster wie yyyy-MM-dd HH:mm:ss, eine vollständige Tabelle der Bezeichner, wie die Kultur die Ausgabe ändert, ISO 8601 als Round-trip mit "o" und die Fehler mit mm vs. MM und hh vs. HH.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

DateTime.ToString(format) macht aus einem Datum Text. Das Format ist entweder ein Standardformatstring (ein einzelner Buchstabe wie d oder o, dessen genaues Muster aus der Kultur kommt) oder ein benutzerdefiniertes Muster aus Bezeichnern wie yyyy, MM und HH. Dieselben Strings funktionieren in der Interpolation, $"{date:yyyy-MM-dd}", und in string.Format.

Ausgabe:

2026-10-09
2026-10-09 18:30:07
09/10/2026
Oct 9, 2026
Friday, October 9
6:30 PM
18:30:07.045
Shipped 2026-10-09 at 18:30

Die Beispiele auf dieser Seite übergeben CultureInfo.InvariantCulture, damit die Ausgabe auf jedem Rechner gleich ist; ohne sie verwendet ToString die aktuelle Kultur, die Monatsnamen, Trennzeichen und sogar den Kalender ändern kann.

Benutzerdefinierte Formatbezeichner

Ein benutzerdefiniertes Format ist ein Muster, in dem bestimmte Buchstaben für Teile des Datums stehen. Sie unterscheiden Groß- und Kleinschreibung: M ist der Monat und m die Minute, H die Stunde im 24-Stunden-Format und h die im 12-Stunden-Format.

BezeichnerBedeutungBeispiel für 2026-10-09 18:30:07.045
yyyyJahr, 4 Ziffern2026
yyJahr, 2 Ziffern26
MMMMVollständiger MonatsnameOctober
MMMAbgekürzter MonatsnameOct
MMMonat, 2 Ziffern10
MMonat, 1 oder 2 Ziffern10
ddddVollständiger TagesnameFriday
dddAbgekürzter TagesnameFri
ddTag des Monats, 2 Ziffern09
dTag des Monats, 1 oder 2 Ziffern (in einem Muster)9
HHStunde, 00 bis 2318
HStunde, 0 bis 2318
hhStunde, 01 bis 1206
hStunde, 1 bis 126
mmMinute, 2 Ziffern30
ssSekunde, 2 Ziffern07
fffMillisekunden045
fffffffTicks (sieben Nachkommastellen)0450000
ttAM/PM-KennzeichnungPM
zzzVersatz zu UTC (DateTimeOffset oder lokale Zeit)+02:00
KZoneninformation: Z, ein Versatz oder nichtsZ (bei einem UTC-Wert)
/Das Datumstrennzeichen der Kultur/ oder . oder -
:Das Zeittrennzeichen der Kultur:
'text' oder \cWörtlicher Text oder wörtliches Zeichen'at'

Jedes andere Zeichen wird unverändert übernommen. Das gilt auch für Buchstaben, die keine Bezeichner sind, weshalb "YYYY-DD" stillschweigend YYYY-DD ausgibt: In .NET gibt es keinen Bezeichner Y oder D in Großschreibung.

Ein einzelner Buchstabe für sich wird als Standardformat gelesen, nicht als benutzerdefiniertes: ToString("d") ist das kurze Datumsmuster, nicht die Tageszahl. Um nur den Tag zu bekommen, schreibe ToString("%d") oder nimm die Property Day.

Ausgabe:

10/09/2026
9
20261009_183007
Week of Oct 9
18h30
2026-10-09T18:30:07
YYYY-DD

Standardformatstrings

Standardformate sind einzelne Buchstaben, deren tatsächliches Muster von der Kultur festgelegt wird. Sie sind die richtige Wahl für Text, der Benutzern angezeigt wird, weil jede Kultur ihre eigenen Konventionen automatisch bekommt.

Ausgabe:

d  10/09/2026
D  Friday, 09 October 2026
f  Friday, 09 October 2026 18:30
g  10/09/2026 18:30
G  10/09/2026 18:30:07
M  October 09
Y  2026 October
t  18:30
T  18:30:07
o  2026-10-09T18:30:07.0000000Z
s  2026-10-09T18:30:07
u  2026-10-09 18:30:07Z
r  Fri, 09 Oct 2026 18:30:07 GMT
en-US d: 10/9/2026, D: Friday, October 9, 2026
CodeNameKulturabhängig?
d / DKurzes / langes DatumJa
t / TKurze / lange UhrzeitJa
f / FLanges Datum mit kurzer / langer UhrzeitJa
g / GKurzes Datum mit kurzer / langer UhrzeitJa
MMonat und TagJa
YJahr und MonatJa
oRound-trip ISO 8601, 7 Nachkommastellen, ZoneNein
sSortierbares ISO 8601, ohne Sekundenbruchteile, ohne ZoneNein
uUniversell sortierbar, endet auf ZNein
rRFC 1123, für HTTP-HeaderNein

o, s, u und r erzeugen in jeder Kultur denselben Text und sind daher sicher für Logs, Dateinamen und Datenaustausch. Beachte, dass u und r bei einem DateTime den Wert nicht in UTC umwandeln; sie geben ihn so aus, wie er ist, und kennzeichnen ihn als UTC. Rufe also zuerst ToUniversalTime() auf (oder nimm DateTime.UtcNow), wenn der Wert lokal ist. (Bei einem DateTimeOffset wandeln sie um.)

Die Kultur ändert die Ausgabe

Die Standardformate, die Monats- und Tagesnamen und die Trennzeichen / und : kommen alle aus der Kultur. Übergib eine als zweites Argument an ToString:

Ausgabe:

en-US  10/9/2026
en-GB  09/10/2026
de-DE  09.10.2026
fr-FR  09/10/2026
ja-JP  2026/10/09
Freitag, 9. Oktober 2026
vendredi 9 octobre 2026
09.10.2026
09/10/2026

Kulturdaten sind nicht eingefroren. .NET unter Linux und macOS liest sie aus der auf dem System installierten ICU-Bibliothek, und seit .NET 5 tut das auch .NET unter Windows 10 und neuer (.NET Framework nutzt die eigenen NLS-Daten von Windows). Ein Muster kann sich also zwischen Versionen und Plattformen leicht ändern: Neuere ICU-Releases setzen im kurzen US-Zeitformat zum Beispiel ein schmales geschütztes Leerzeichen statt eines normalen Leerzeichens vor „PM“, und manche liefern spanische Kurzdaten ohne führende Null. Ein Grund mehr, nie Text zu parsen, der für die Anzeige formatiert wurde.

Daraus folgen zwei Regeln. Für Text, den ein Mensch liest, formatiere mit seiner Kultur (auf einem Server mit der aus der Anfrage, nicht mit der des Servers) und bevorzuge Standardformate, sodass ein deutscher Leser 09.10.2026 sieht und ein amerikanischer 10/9/2026. Für Text, den ein Programm liest, nimm CultureInfo.InvariantCulture und ein eindeutiges Muster wie yyyy-MM-dd oder o. Ein Datum, das mit der aktuellen Kultur geschrieben und auf einem anderen Rechner geparst wird, ist eine klassische Quelle vertauschter Tage und Monate.

ISO 8601 und Round-trip mit "o"

Das Round-trip-Format "o" schreibt jeden Tick plus die Zoneninformation, das Parsen des Texts ergibt also genau denselben DateTime, einschließlich seines Kind:

Ausgabe:

2026-10-09T18:30:07.0450000Z
2026-10-09T18:30:07.0450000
2026-10-09T20:30:07.0000000+02:00
True
Utc
2026-10-09T18:30:07Z
2026-10-09 20:30 +02:00

Das Suffix Z kennzeichnet UTC; ein DateTime mit Kind Unspecified bekommt kein Suffix; eine lokale Zeit oder ein DateTimeOffset bekommt ihren Versatz (+02:00). Parse mit DateTimeStyles.RoundtripKind, damit Kind erhalten bleibt. JSON-Serializer, Datenbanken und Date in JavaScript lesen dieses Format alle.

TimeSpan formatieren

TimeSpan hat eine eigene, kleinere Menge benutzerdefinierter Bezeichner: d (Tage), hh, mm, ss und fff. Anders als bei DateTime muss jedes wörtliche Zeichen, auch : und ., mit einem Backslash escaped oder in Anführungszeichen gesetzt werden:

Ausgabe:

1.03:25:09.1200000
1.03:25:09.1200000
03:25:09
1.03:25
25:09.120
27:25

hh ist in einem TimeSpan-Format die Stundenkomponente (0 bis 23), eine Dauer von 27 Stunden wird also als 03 ausgegeben. Für Summen über einen Tag rechne wie in der letzten Zeile mit TotalHours. elapsed.ToString("hh:mm") ohne den Backslash wirft eine FormatException.

Häufige Fehler

  • mm für den Monat. "yyyy-mm-dd" gibt in der Mitte Minuten aus: 2026-30-09. Der Monat ist MM.
  • hh ohne tt. "hh:mm" ist eine 12-Stunden-Uhr ohne AM oder PM, 06:30 ist also mehrdeutig. Nimm HH für die 24-Stunden-Zeit.
  • YYYY und DD. In .NET keine Bezeichner; sie werden wörtlich ausgegeben. Nimm yyyy und dd.
  • / in einem Muster für Daten. Es ist das Datumstrennzeichen der Kultur. Setze es in Anführungszeichen oder nimm die invariante Kultur.
  • Standard-ToString() in Logs oder Dateien. Das Format hängt vom Rechner ab. Übergib ein Format und eine Kultur.
  • Lokale Zeit als UTC gekennzeichnet. "u", "r" und ein von Hand geschriebenes 'Z' wandeln nicht um; wandle vorher um.
  • Mit einem anderen Muster parsen, als du geschrieben hast. Halte Formatstrings für Daten in einer Konstante und verwende sie sowohl mit ToString als auch mit ParseExact.

Häufig gestellte Fragen

Wie formatiere ich in C# einen DateTime als yyyy-MM-dd?

date.ToString("yyyy-MM-dd") ergibt 2026-10-09. In einem interpolierten String schreibst du $"{date:yyyy-MM-dd}". Hänge " HH:mm:ss" für die Uhrzeit im 24-Stunden-Format an. Übergib CultureInfo.InvariantCulture als zweites Argument, wenn der Text für eine Datei oder ein anderes Programm bestimmt ist, damit Kalender, Monatsnamen und Trennzeichen nie vom Rechner abhängen.

Was ist der Unterschied zwischen mm und MM in C#-Datumsformaten?

MM ist der Monat (01 bis 12) und mm die Minute (00 bis 59). Das Format unterscheidet Groß- und Kleinschreibung, yyyy-mm-dd gibt also die Minuten dort aus, wo der Monat stehen sollte, ein Bug, der bei einem flüchtigen Blick auf einen einzelnen Wert leicht übersehen wird. Ebenso ist HH die Stunde im 24-Stunden-Format und hh die Stunde im 12-Stunden-Format.

Wie formatiere ich in C# einen DateTime nach ISO 8601?

Nimm das Round-trip-Format "o": DateTime.UtcNow.ToString("o") ergibt 2026-10-09T18:30:07.0450000Z, mit sieben Nachkommastellen und einem Z für UTC oder einem Versatz bei lokalen Zeiten. "s" ergibt die kürzere sortierbare Form ohne Sekundenbruchteile und Zone, und "yyyy-MM-ddTHH:mm:ssZ" ist eine verbreitete benutzerdefinierte Variante.

Wie zeige ich AM und PM in einem C#-Datumsformat an?

Nimm hh oder h für die 12-Stunden-Uhr und tt für die AM/PM-Kennzeichnung: date.ToString("h:mm tt", CultureInfo.GetCultureInfo("en-US")) ergibt 6:30 PM. Die Kennzeichnung kommt aus der Kultur, und manche Kulturen haben keine, übergib also explizit eine Kultur, wenn du AM und PM brauchst.

Warum zeigt mein Datumsformat Punkte statt Schrägstriche?

In einem Formatstring ist / kein wörtlicher Schrägstrich, sondern das Datumstrennzeichen der Kultur, und : ist das Zeittrennzeichen der Kultur. Auf einem deutschen Rechner gibt dd/MM/yyyy den Text 09.10.2026 aus. Setze das Zeichen in Anführungszeichen, um es zu erzwingen, dd'/'MM'/'yyyy, oder formatiere mit CultureInfo.InvariantCulture.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S