DateTime.ToString(format) trasforma una data in testo. Il formato è una stringa di formato standard (una sola lettera come d o o, il cui pattern esatto dipende dalla cultura) oppure un pattern personalizzato costruito con specificatori come yyyy, MM e HH. Le stesse stringhe funzionano nell'interpolazione, $"{date:yyyy-MM-dd}", e in string.Format.
Output:
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
Gli esempi di questa pagina passano CultureInfo.InvariantCulture perché l'output sia uguale su ogni macchina; senza, ToString usa la cultura corrente, che può cambiare i nomi dei mesi, i separatori e persino il calendario.
Specificatori di formato personalizzati
Un formato personalizzato è un pattern in cui certe lettere rappresentano parti della data. Distinguono maiuscole e minuscole: M è il mese e m il minuto, H è l'ora nel formato 24 ore e h quella nel formato 12 ore.
| Specificatore | Significato | Esempio per 2026-10-09 18:30:07.045 |
|---|---|---|
yyyy | Anno, 4 cifre | 2026 |
yy | Anno, 2 cifre | 26 |
MMMM | Nome completo del mese | October |
MMM | Nome abbreviato del mese | Oct |
MM | Mese, 2 cifre | 10 |
M | Mese, 1 o 2 cifre | 10 |
dddd | Nome completo del giorno | Friday |
ddd | Nome abbreviato del giorno | Fri |
dd | Giorno del mese, 2 cifre | 09 |
d | Giorno del mese, 1 o 2 cifre (in un pattern) | 9 |
HH | Ora, da 00 a 23 | 18 |
H | Ora, da 0 a 23 | 18 |
hh | Ora, da 01 a 12 | 06 |
h | Ora, da 1 a 12 | 6 |
mm | Minuto, 2 cifre | 30 |
ss | Secondo, 2 cifre | 07 |
fff | Millisecondi | 045 |
fffffff | Tick (sette cifre frazionarie) | 0450000 |
tt | Indicatore AM/PM | PM |
zzz | Offset da UTC (DateTimeOffset o ora locale) | +02:00 |
K | Informazioni sul fuso: Z, un offset o niente | Z (per un valore UTC) |
/ | Il separatore delle date della cultura | / o . o - |
: | Il separatore delle ore della cultura | : |
'text' o \c | Testo o carattere letterale | 'at' |
Qualsiasi altro carattere viene copiato così com'è. Questo vale anche per le lettere che non sono specificatori, ed è così che "YYYY-DD" stampa tranquillamente YYYY-DD: in .NET non esistono gli specificatori Y o D maiuscoli.
Una sola lettera da sola viene letta come formato standard, non personalizzato: ToString("d") è il pattern della data breve, non il numero del giorno. Per avere solo il giorno scrivi ToString("%d") oppure usa la proprietà Day.
Output:
10/09/2026
9
20261009_183007
Week of Oct 9
18h30
2026-10-09T18:30:07
YYYY-DD
Stringhe di formato standard
I formati standard sono singole lettere il cui pattern effettivo è definito dalla cultura. Sono la scelta giusta per il testo mostrato agli utenti, perché ogni cultura ottiene gratis le proprie convenzioni.
Output:
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
| Codice | Nome | Dipende dalla cultura? |
|---|---|---|
d / D | Data breve / lunga | Sì |
t / T | Ora breve / lunga | Sì |
f / F | Data lunga con ora breve / lunga | Sì |
g / G | Data breve con ora breve / lunga | Sì |
M | Mese e giorno | Sì |
Y | Anno e mese | Sì |
o | ISO 8601 round-trip, 7 cifre frazionarie, fuso | No |
s | ISO 8601 ordinabile, senza frazioni, senza fuso | No |
u | Universale ordinabile, termina con Z | No |
r | RFC 1123, per gli header HTTP | No |
o, s, u e r producono lo stesso testo in ogni cultura, il che li rende sicuri per log, nomi di file e scambio di dati. Nota che su un DateTime, u e r non convertono il valore in UTC; lo stampano così com'è e lo etichettano come UTC, quindi chiama prima ToUniversalTime() (o usa DateTime.UtcNow) se il valore è locale. (Su un DateTimeOffset invece convertono.)
La cultura cambia l'output
I formati standard, i nomi dei mesi e dei giorni e i separatori / e : arrivano tutti dalla cultura. Passane una come secondo argomento di ToString:
Output:
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
I dati di cultura non sono congelati. .NET su Linux e macOS li legge dalla libreria ICU installata nel sistema, e da .NET 5 lo fa anche .NET su Windows 10 e successivi (.NET Framework usa i dati NLS di Windows), quindi un pattern può cambiare leggermente tra versioni e piattaforme: le versioni recenti di ICU, per esempio, mettono uno spazio stretto indivisibile invece di uno spazio normale prima di "PM" nel formato dell'ora breve statunitense, e alcune danno le date brevi spagnole senza lo zero iniziale. Un motivo in più per non analizzare mai testo formattato per la visualizzazione.
Ne derivano due regole. Per il testo che legge una persona, formatta con la sua cultura (su un server, quella della richiesta, non quella del server) e preferisci i formati standard, così un lettore tedesco vede 09.10.2026 e uno americano 10/9/2026. Per il testo che legge un programma, usa CultureInfo.InvariantCulture e un pattern non ambiguo come yyyy-MM-dd o o. Una data scritta con la cultura corrente e analizzata su un'altra macchina è una fonte classica di giorni e mesi scambiati.
ISO 8601 e round-trip con "o"
Il formato round-trip "o" scrive ogni tick più le informazioni sul fuso, quindi analizzando il testo si ottiene esattamente lo stesso DateTime, compreso il suo Kind:
Output:
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
Il suffisso Z indica UTC; un DateTime con Kind Unspecified non riceve alcun suffisso; un'ora locale o un DateTimeOffset riceve il suo offset (+02:00). Analizza con DateTimeStyles.RoundtripKind perché il Kind venga conservato. I serializzatori JSON, i database e il Date di JavaScript leggono tutti questo formato.
Formattare un TimeSpan
TimeSpan ha un proprio insieme più ridotto di specificatori personalizzati: d (giorni), hh, mm, ss e fff. A differenza di DateTime, ogni carattere letterale, compresi : e ., va preceduto da una barra rovesciata o messo tra apici:
Output:
1.03:25:09.1200000
1.03:25:09.1200000
03:25:09
1.03:25
25:09.120
27:25
hh in un formato TimeSpan è la componente delle ore (da 0 a 23), quindi una durata di 27 ore viene stampata come 03. Per totali superiori a un giorno, calcola a partire da TotalHours come nell'ultima riga. elapsed.ToString("hh:mm") senza la barra rovesciata lancia una FormatException.
Errori comuni
mmper il mese."yyyy-mm-dd"stampa i minuti al centro:2026-30-09. Il mese èMM.hhsenzatt."hh:mm"è un orologio a 12 ore senza AM né PM, quindi 06:30 è ambiguo. UsaHHper l'ora nel formato 24 ore.YYYYeDD. In .NET non sono specificatori; vengono stampati letteralmente. Usayyyyedd./in un pattern per i dati. È il separatore delle date della cultura. Mettilo tra apici o usa la cultura invariante.ToString()predefinito nei log o nei file. Il formato dipende dalla macchina. Passa un formato e una cultura.- Ora locale etichettata come UTC.
"u","r"e una'Z'scritta a mano non convertono; converti prima. - Analizzare con un pattern diverso da quello usato per scrivere. Tieni le stringhe di formato per i dati in un'unica costante e usala sia con
ToStringsia conParseExact.
Domande frequenti
Come formatto un DateTime come yyyy-MM-dd in C#?
date.ToString("yyyy-MM-dd") restituisce 2026-10-09. In una stringa interpolata scrivi $"{date:yyyy-MM-dd}". Aggiungi " HH:mm:ss" per l'ora nel formato 24 ore. Passa CultureInfo.InvariantCulture come secondo argomento quando il testo è destinato a un file o a un altro programma, così calendario, nomi dei mesi e separatori non dipendono mai dalla macchina.
Che differenza c'è tra mm e MM nei formati di data C#?
MM è il mese (da 01 a 12) e mm è il minuto (da 00 a 59). Il formato distingue maiuscole e minuscole, quindi yyyy-mm-dd stampa i minuti al posto del mese, un bug facile da non notare se guardi un solo valore. Allo stesso modo HH è l'ora nel formato 24 ore e hh quella nel formato 12 ore.
Come formatto un DateTime in ISO 8601 in C#?
Usa il formato round-trip "o": DateTime.UtcNow.ToString("o") restituisce 2026-10-09T18:30:07.0450000Z, con sette cifre frazionarie e una Z per UTC oppure un offset per le ore locali. "s" dà la forma ordinabile più breve senza frazioni né fuso, e "yyyy-MM-ddTHH:mm:ssZ" è una variante personalizzata comune.
Come mostro AM e PM in un formato di data C#?
Usa hh o h per l'orologio a 12 ore e tt per l'indicatore AM/PM: date.ToString("h:mm tt", CultureInfo.GetCultureInfo("en-US")) restituisce 6:30 PM. L'indicatore arriva dalla cultura, e alcune culture non ne hanno, quindi passa una cultura esplicita quando ti servono AM e PM.
Perché il mio formato di data mostra punti invece delle barre?
In una stringa di formato, / non è una barra letterale ma il separatore delle date della cultura, e : è il separatore delle ore della cultura. Su una macchina tedesca dd/MM/yyyy stampa 09.10.2026. Metti il carattere tra apici per forzarlo, dd'/'MM'/'yyyy, oppure formatta con CultureInfo.InvariantCulture.