C# - Ottieni un DateTime o DateTimeOffset in formato UTC o un formato di fuso orario

C# - Ottieni un DateTime o DateTimeOffset in formato UTC o un formato di fuso orario

La maggior parte delle API che incontri utilizzano uno standard per il formato di date e ora, spesso sarà il formato ISO 8601, noto come modello di data/ora di andata e ritorno. Puoi ottenere questo formato standard da un DateTime fornendo il parametro "O" a un ToString chiama, tuttavia ci sono alcuni trucchi a cui prestare attenzione.

DateTimeKind diverso fornisce un output ToString("O") diverso

Puoi usare il ToString metodo sulla struttura DateTime nel modo seguente:

var dateTimeNowS = DateTime.Now.ToString("O");
//dateTimeNowS is "2022-01-21T22:06:21.9883794+02:00"

Questo ti dà il formato "2022-01-21T22:06:21.9883794+02:00" che ha un'alta precisione e un fuso orario, il fuso orario è il tuo offset locale, per me in Danimarca è +02:00. In alternativa avresti potuto definire tu stesso il formato usando quanto segue, che darebbe lo stesso identico risultato:

var dateTimeNowCustomS = DateTime.Now.
   ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK");
//dateTimeNowCustomS is "2022-01-21T22:06:21.9883794+02:00"

Puoi leggere ulteriori informazioni sulla creazione di formati specifici per DateTime qui.

Potresti esserti aspettato di ottenere il formato UTC, noto come formato "zero offset", che è anche facilmente riconoscibile grazie alla "Z" maiuscola alla fine. Comunque la chiamata al ToString il metodo di DateTime lo restituirà solo se DateTime è del tipo "UTC". Internamente la struttura DateTime tiene traccia se si tratta di un DateTime locale, UTC o non specificato e il ToString metodo agisce di conseguenza. Se avessimo usato UtcNow invece di .Now avremmo ottenuto un DateTime UTC:

var dateTimeUtcNowS = DateTime.UtcNow.ToString("O");
//dateTimeUtcNowS is "2022-01-21T20:11:59.0102110Z"

Come nell'esempio precedente, puoi specificare il formato da solo se preferisci:

var dateTimeNowUtcCustomS = DateTime.UtcNow.
   ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK");
//dateTimeNowUtcCustomS is "2022-01-21T20:11:59.0102110Z"

A causa del modo in cui il K nella stringa fornita per ToString opera, il fuso orario viene omesso su Datetimes nell'ora UTC.

Ottieni il formato UTC da DateTime locale e viceversa

Puoi sempre cambiare il tipo di DateTIme da Local a UTC usando il ToUniversalTime metodo come mostrato di seguito:

var dateTimeNow = DateTime.Now;
var dateTimeNowS = dateTimeNow.ToString("O");
//dateTimeNowS is "2022-01-21T22:06:21.9883794+02:00"

var dateTimeNowUtc = dateTimeNow.ToUniversalTime(); //ToUniversalTime
var dateTimeNowUtcS = dateTimeNowUtc.ToString("O");
//dateTimeNowUtcS is "2022-01-21T20:06:21.9883794Z"

E puoi ottenere l'effetto inverso chiamando il ToLocalTime metodo:

var dateTimeNowUtc = DateTime.UtcNow;
var dateTimeNowUtcS = dateTimeNowUtc.ToString("O");
//dateTimeNowUtcS is "2022-01-21T20:06:21.9883794Z"

var dateTimeNow = dateTimeNowUtc.ToLocalTime(); //ToLocalTime
var dateTimeNowS = dateTimeNow.ToString("O");
//dateTimeNowS is "2022-01-21T22:06:21.9883794+02:00"

DateTimeKind non specificato

Oltre all'UTC e al DateTimeKind locale esiste anche il tipo Unspecified. Ad esempio, un DateTime non è specificato se viene analizzato da una stringa e non viene fornito un fuso orario o un formato UTC corretto. In questo modo non abbiamo alcuna possibilità di sapere quale sia il fuso orario ed è quindi "non specificato". Il DateTime non specificato fornisce un terzo tipo di formato quando ToString("O") si chiama:

var dateTimeNowUnspecified = 
    DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);
var dateTimeNowUnspecifiedS = dateTimeNowUnspecified.ToString("O");
//dateTimeNowUnspecifiedS is "2022-01-21T22:37:18.5056238"

Formato DateTimeOffset

Nota per DateTimeOffset ottieni sempre il formato con un fuso orario quando chiami ToString("O") :

var dateTimeOffsetNow = DateTimeOffset.Now;
var dateTimeOffsetNowS = dateTimeOffsetNow.ToString("O");
//dateTimeOffsetNowS is "2022-08-21T22:44:55.5370212+02:00"

var dateTimeOffsetUtcNow = DateTimeOffset.UtcNow;
var dateTimeOffsetUtcNowS = dateTimeOffsetUtcNow.ToString("O");
//dateTimeOffsetUtcNowS is "2022-08-21T20:44:55.5370212+00:00"

Sia che chiami UtcNow o solo Now ti ritroverai con lo stesso formato. Poiché DateTimeOffset si basa su offset anziché su DateTimeKind. L'offset sarà diverso per UtcNow poiché ti darà sempre l'offset aggiustato +00:00.

Puoi ottenere un formato "zero offset" convertendolo prima in un DateTime di tipo UTC:

var dateTimeOffsetNow = DateTimeOffset.Now;
var dateTimeOffsetNowS = dateTimeOffsetNow.UtcDateTime.ToString("O");
//dateTimeNowUtcS is "2022-01-21T20:55:33.0794136Z"

Ecco fatto

Spero che tu l'abbia trovato utile. Microsoft ha un'ottima documentazione su questo argomento, tuttavia è piuttosto lunga e travolgente. Fatemi sapere nei commenti in basso cosa ne pensate di questa versione più breve!