DateTime.ToString(format) zamienia datę na tekst. Format to albo standardowy ciąg formatu (jedna litera, taka jak d lub o, której dokładny wzorzec pochodzi z kultury), albo niestandardowy wzorzec zbudowany ze specyfikatorów takich jak yyyy, MM i HH. Te same ciągi działają w interpolacji, $"{date:yyyy-MM-dd}", i w string.Format.
Wynik:
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
Przykłady na tej stronie przekazują CultureInfo.InvariantCulture, żeby wynik był taki sam na każdej maszynie; bez tego ToString używa bieżącej kultury, która może zmienić nazwy miesięcy, separatory, a nawet kalendarz.
Niestandardowe specyfikatory formatu
Format niestandardowy to wzorzec, w którym określone litery oznaczają części daty. Rozróżniają wielkość liter: M to miesiąc, a m to minuta, H to godzina w formacie 24-godzinnym, a h w 12-godzinnym.
| Specyfikator | Znaczenie | Przykład dla 2026-10-09 18:30:07.045 |
|---|---|---|
yyyy | Rok, 4 cyfry | 2026 |
yy | Rok, 2 cyfry | 26 |
MMMM | Pełna nazwa miesiąca | October |
MMM | Skrócona nazwa miesiąca | Oct |
MM | Miesiąc, 2 cyfry | 10 |
M | Miesiąc, 1 lub 2 cyfry | 10 |
dddd | Pełna nazwa dnia | Friday |
ddd | Skrócona nazwa dnia | Fri |
dd | Dzień miesiąca, 2 cyfry | 09 |
d | Dzień miesiąca, 1 lub 2 cyfry (we wzorcu) | 9 |
HH | Godzina, od 00 do 23 | 18 |
H | Godzina, od 0 do 23 | 18 |
hh | Godzina, od 01 do 12 | 06 |
h | Godzina, od 1 do 12 | 6 |
mm | Minuta, 2 cyfry | 30 |
ss | Sekunda, 2 cyfry | 07 |
fff | Milisekundy | 045 |
fffffff | Takty (siedem cyfr ułamkowych) | 0450000 |
tt | Oznaczenie AM/PM | PM |
zzz | Przesunięcie względem UTC (DateTimeOffset lub czas lokalny) | +02:00 |
K | Informacja o strefie: Z, przesunięcie albo nic | Z (dla wartości UTC) |
/ | Separator daty z kultury | / lub . lub - |
: | Separator czasu z kultury | : |
'text' lub \c | Dosłowny tekst lub znak | 'at' |
Każdy inny znak jest kopiowany bez zmian. Dotyczy to także liter, które nie są specyfikatorami, dlatego "YYYY-DD" po cichu wypisuje YYYY-DD: w .NET nie ma specyfikatorów z wielkim Y ani D.
Pojedyncza litera sama w sobie jest czytana jako format standardowy, a nie niestandardowy: ToString("d") to wzorzec krótkiej daty, a nie numer dnia. Żeby dostać sam dzień, napisz ToString("%d") albo użyj właściwości Day.
Wynik:
10/09/2026
9
20261009_183007
Week of Oct 9
18h30
2026-10-09T18:30:07
YYYY-DD
Standardowe ciągi formatu
Formaty standardowe to pojedyncze litery, których faktyczny wzorzec określa kultura. Są właściwym wyborem dla tekstu pokazywanego użytkownikom, bo każda kultura dostaje za darmo własne konwencje.
Wynik:
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
| Kod | Nazwa | Zależy od kultury? |
|---|---|---|
d / D | Krótka / długa data | Tak |
t / T | Krótki / długi czas | Tak |
f / F | Długa data z krótkim / długim czasem | Tak |
g / G | Krótka data z krótkim / długim czasem | Tak |
M | Miesiąc i dzień | Tak |
Y | Rok i miesiąc | Tak |
o | ISO 8601 round-trip, 7 cyfr ułamkowych, strefa | Nie |
s | Sortowalny ISO 8601, bez ułamków, bez strefy | Nie |
u | Uniwersalny sortowalny, kończy się na Z | Nie |
r | RFC 1123, dla nagłówków HTTP | Nie |
o, s, u i r dają ten sam tekst w każdej kulturze, dlatego są bezpieczne w logach, nazwach plików i wymianie danych. Pamiętaj, że dla DateTime formaty u i r nie konwertują wartości na UTC; wypisują ją bez zmian i oznaczają jako UTC, więc jeśli wartość jest lokalna, najpierw wywołaj ToUniversalTime() (albo użyj DateTime.UtcNow). (Dla DateTimeOffset konwertują.)
Kultura zmienia wynik
Formaty standardowe, nazwy miesięcy i dni oraz separatory / i : pochodzą z kultury. Przekaż ją jako drugi argument ToString:
Wynik:
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
Dane kultur nie są zamrożone. .NET na Linuksie i macOS odczytuje je z biblioteki ICU zainstalowanej w systemie, a od .NET 5 robi to również .NET na Windows 10 i nowszych (.NET Framework używa własnych danych NLS z Windows), więc wzorzec może się nieznacznie zmieniać między wersjami i platformami: na przykład nowsze wydania ICU wstawiają przed "PM" w amerykańskim formacie krótkiego czasu wąską spację nierozdzielającą zamiast zwykłej spacji, a niektóre podają hiszpańskie krótkie daty bez zera na początku. To kolejny powód, żeby nigdy nie parsować tekstu sformatowanego do wyświetlania.
Wynikają z tego dwie zasady. Tekst czytany przez człowieka formatuj w jego kulturze (na serwerze w kulturze z żądania, a nie serwera) i wybieraj formaty standardowe, żeby czytelnik z Niemiec zobaczył 09.10.2026, a z USA 10/9/2026. Tekst czytany przez program formatuj z CultureInfo.InvariantCulture i jednoznacznym wzorcem, takim jak yyyy-MM-dd lub o. Data zapisana w bieżącej kulturze i sparsowana na innej maszynie to klasyczne źródło zamienionych dni i miesięcy.
ISO 8601 i round-trip z "o"
Format round-trip "o" zapisuje każdy takt oraz informację o strefie, więc sparsowanie tekstu zwraca dokładnie ten sam DateTime, łącznie z jego Kind:
Wynik:
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
Przyrostek Z oznacza UTC; DateTime z Kind równym Unspecified nie dostaje przyrostka; czas lokalny lub DateTimeOffset dostaje swoje przesunięcie (+02:00). Parsuj z DateTimeStyles.RoundtripKind, żeby Kind się zachował. Serializatory JSON, bazy danych i Date w JavaScripcie odczytują ten format.
Formatowanie TimeSpan
TimeSpan ma własny, mniejszy zestaw specyfikatorów niestandardowych: d (dni), hh, mm, ss i fff. W przeciwieństwie do DateTime każdy dosłowny znak, w tym : i ., trzeba poprzedzić ukośnikiem wstecznym albo ująć w cudzysłów:
Wynik:
1.03:25:09.1200000
1.03:25:09.1200000
03:25:09
1.03:25
25:09.120
27:25
hh w formacie TimeSpan to składnik godzin (od 0 do 23), więc czas trwania 27 godzin wypisuje się jako 03. Dla sum powyżej doby licz z TotalHours, jak w ostatniej linii. elapsed.ToString("hh:mm") bez ukośnika wstecznego rzuca FormatException.
Częste błędy
mmjako miesiąc."yyyy-mm-dd"wypisuje minuty w środku:2026-30-09. Miesiąc toMM.hhbeztt."hh:mm"to zegar 12-godzinny bez AM i PM, więc 06:30 jest niejednoznaczne. Dla czasu 24-godzinnego użyjHH.YYYYiDD. W .NET to nie są specyfikatory; wypisują się dosłownie. Użyjyyyyidd./we wzorcu dla danych. To separator daty z kultury. Ujmij go w cudzysłów albo użyj kultury niezmiennej.- Domyślne
ToString()w logach lub plikach. Format zależy od maszyny. Przekaż format i kulturę. - Czas lokalny oznaczony jako UTC.
"u","r"i ręcznie wpisane'Z'nie konwertują; najpierw skonwertuj. - Parsowanie innym wzorcem niż ten użyty przy zapisie. Trzymaj ciągi formatu dla danych w jednej stałej i używaj jej zarówno w
ToString, jak i wParseExact.
Najczęściej zadawane pytania
Jak sformatować DateTime jako yyyy-MM-dd w C#?
date.ToString("yyyy-MM-dd") daje 2026-10-09. W napisie interpolowanym napisz $"{date:yyyy-MM-dd}". Dodaj " HH:mm:ss", żeby dostać godzinę w formacie 24-godzinnym. Gdy tekst trafia do pliku lub innego programu, przekaż CultureInfo.InvariantCulture jako drugi argument, żeby kalendarz, nazwy miesięcy i separatory nigdy nie zależały od maszyny.
Czym różni się mm od MM w formatach dat C#?
MM to miesiąc (od 01 do 12), a mm to minuta (od 00 do 59). Format rozróżnia wielkość liter, więc yyyy-mm-dd wypisuje minuty tam, gdzie powinien być miesiąc, a taki błąd łatwo przeoczyć, patrząc na jedną wartość. Podobnie HH to godzina w formacie 24-godzinnym, a hh w 12-godzinnym.
Jak sformatować DateTime w ISO 8601 w C#?
Użyj formatu round-trip "o": DateTime.UtcNow.ToString("o") daje 2026-10-09T18:30:07.0450000Z, z siedmioma cyframi ułamkowymi i Z dla UTC albo przesunięciem dla czasu lokalnego. "s" daje krótszą, sortowalną postać bez ułamków i strefy, a "yyyy-MM-ddTHH:mm:ssZ" to popularny wariant niestandardowy.
Jak pokazać AM i PM w formacie daty C#?
Użyj hh lub h dla zegara 12-godzinnego i tt dla oznaczenia AM/PM: date.ToString("h:mm tt", CultureInfo.GetCultureInfo("en-US")) daje 6:30 PM. Oznaczenie pochodzi z kultury, a niektóre kultury go nie mają, więc gdy potrzebujesz AM i PM, przekaż kulturę jawnie.
Dlaczego mój format daty pokazuje kropki zamiast ukośników?
W ciągu formatu / nie jest dosłownym ukośnikiem, tylko separatorem daty z kultury, a : to separator czasu z kultury. Na niemieckiej maszynie dd/MM/yyyy wypisuje 09.10.2026. Ujmij znak w cudzysłów, żeby go wymusić, dd'/'MM'/'yyyy, albo formatuj z CultureInfo.InvariantCulture.