Come posso formattare DateTime nel formato Web UTC?


89

Ho un DateTime che desidero formattare in " 2009-09-01T00:00:00.000Z", ma il codice seguente mi dà " 2009-09-01T00:00:00.000+01:00" (entrambe le righe):

new DateTime(2009, 9, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffzzz")
new DateTime(2009, 9, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffzzz")

Qualche idea su come farlo funzionare?

Risposte:


160
string foo = yourDateTime.ToUniversalTime()
                         .ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

1
@Downvoter: vuoi dirci cosa pensi ci sia di sbagliato in questa risposta?
LucaH

12
Ha funzionato ma .ToUniversalTime () rovinerà la tua data esistente se è già UTC ma la variabile yourDateTime non lo specifica. Ho finito per rimuovere .ToUniversalTime () e le date sono state quindi allineate con ciò che ci si aspettava ad entrambe le estremità (database e client web).
Robin Vessey

10
Se la data e l'ora della data è già universale, puoi chiamare .ToUniversalTime()quanto vuoi, non la cambierà. - Tuttavia, se hai un valore temporale universale memorizzato come ora locale, ovviamente lo cambierà (ma in tal caso, hai problemi più grandi da affrontare!) - Ad ogni modo, questa risposta è terribile. Dovresti invece usare la "O"stringa di formato come specificato dalla risposta di seguito.
BrainSlugs83

1
@ BrainSlugs83: Questa risposta "terribile" dà in realtà il PO ciò che chiedevano: 2009-09-01T00:00:00.000Z. Utilizzando l'identificatore "O" avrebbe dato loro qualcosa di diverso: 2009-09-01T00:00:00.0000000Z.
LukeH

Documentazione per la formattazione di stringhe personalizzate per DateTime docs.microsoft.com/en-us/dotnet/standard/base-types/…
Mark Hebert

75

Perché non utilizzare semplicemente l'identificatore di formato Round-trip ("O", "o") ?

L'identificatore di formato standard "O" o "o" rappresenta una stringa di formato di data e ora personalizzata utilizzando un modello che conserva le informazioni sul fuso orario ed emette una stringa di risultato conforme a ISO 8601. Per i valori DateTime, questo identificatore di formato è progettato per preservare la data e valori di tempo insieme alla proprietà DateTime.Kind nel testo. La stringa formattata può essere analizzata utilizzando il metodo DateTime.Parse (String, IFormatProvider, DateTimeStyles) o DateTime.ParseExact se il parametro styles è impostato su DateTimeStyles.RoundtripKind.

L'identificatore di formato standard "O" o "o" corrisponde alla stringa di formato personalizzato "yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' FffffffK" per i valori DateTime e al Stringa di formato personalizzato "yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' fffffffzzz" per i valori DateTimeOffset. In questa stringa, le coppie di virgolette singole che delimitano i singoli caratteri, come i trattini, i due punti e la lettera "T", indicano che il singolo carattere è un letterale che non può essere modificato. Gli apostrofi non vengono visualizzati nella stringa di output.

L'identificatore di formato standard O "o" o "(e la stringa di formato personalizzato" yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' FffffffK ") sfrutta i tre modi in cui che ISO 8601 rappresenta le informazioni sul fuso orario per preservare la proprietà Kind dei valori DateTime:

public class Example
{
   public static void Main()
   {
       DateTime dat = new DateTime(2009, 6, 15, 13, 45, 30, 
                                   DateTimeKind.Unspecified);
       Console.WriteLine("{0} ({1}) --> {0:O}", dat, dat.Kind); 

       DateTime uDat = new DateTime(2009, 6, 15, 13, 45, 30, 
                                    DateTimeKind.Utc);
       Console.WriteLine("{0} ({1}) --> {0:O}", uDat, uDat.Kind);

       DateTime lDat = new DateTime(2009, 6, 15, 13, 45, 30, 
                                    DateTimeKind.Local);
       Console.WriteLine("{0} ({1}) --> {0:O}\n", lDat, lDat.Kind);

       DateTimeOffset dto = new DateTimeOffset(lDat);
       Console.WriteLine("{0} --> {0:O}", dto);
   }
}
// The example displays the following output: 
//    6/15/2009 1:45:30 PM (Unspecified) --> 2009-06-15T13:45:30.0000000 
//    6/15/2009 1:45:30 PM (Utc) --> 2009-06-15T13:45:30.0000000Z 
//    6/15/2009 1:45:30 PM (Local) --> 2009-06-15T13:45:30.0000000-07:00 
//     
//    6/15/2009 1:45:30 PM -07:00 --> 2009-06-15T13:45:30.0000000-07:00

Dato che non funziona come richiesto, dopotutto l'hai citato - "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffzzz" non è in formato Zulu.
Astrowalker

@astrowalker Dovrebbe funzionare. Ti ha dato più opzioni nella sua risposta. Devi solo sceglierne uno. Nel tuo caso (e nell'OP), useresti DateTimeKind.Utc per produrre stringhe con "z" alla fine (aka "Formato Zulu" o "Ora UTC"). Basta guardare il suo output di esempio per UTC. Nel mio caso, ho usato: dtVariable.ToUniversalTime().ToString("o")che convertirà in "2019-05-26T19:50:34.4400000Z"o "yyyy-MM-ddTHH:mm:ss.fffffffZ". Nota: l'ho anche testato con il new Date(dtDateString).getTime()metodo Javscript e analizza correttamente la stringa della data prodotta da questo.
MikeTeeVee

@ MikeTeeVee, stavo solo sottolineando che le soluzioni fornite non funzioneranno (per DTO). Il modo appropriato è dto.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF'Z'"). Per la cronaca, "o"aggiunge solo offset, non è il formato Zulu.
astrowalker

1
Per coloro che cercano di fare una trasformazione di stringa:$"{DateTime.UtcNow:O}"
Tiago César Oliveira

18
string.Format("{0:yyyy-MM-ddTHH:mm:ss.FFFZ}", DateTime.UtcNow)

restituisce 2017-02-10T08: 12: 39.483Z


6

Il formato migliore da utilizzare è "aaaa" - 'MM' - 'gg'T'HH': 'mm': 'ss'. 'FffK ".

L'ultima K sulla stringa verrà modificata in "Z" se la data è UTC o con fuso orario (+ -hh: mm) se è locale. ( http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx )

Come ha detto LukeH, è bene usare ToUniversalTime se vuoi che tutte le date siano UTC.

Il codice finale è:

string foo = yourDateTime.ToUniversalTime()
                         .ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK");

6

Alcune persone hanno sottolineato che "ToUniversalTime" è alquanto pericoloso in quanto può causare una visualizzazione errata del tempo non intenzionale. Espandendo questo, sto fornendo un esempio più dettagliato di una soluzione. L'esempio qui crea un'estensione per l'oggetto DateTime che restituisce in modo sicuro un UTC DateTime dove è possibile utilizzare ToString come desiderato….

class Program
{
    static void Main(string[] args)
    {
        DateTime dUtc = new DateTime(2016, 6, 1, 3, 17, 0, 0, DateTimeKind.Utc);
        DateTime dUnspecified = new DateTime(2016, 6, 1, 3, 17, 0, 0, DateTimeKind.Unspecified);

        //Sample of an unintended mangle:
        //Prints "2016-06-01 10:17:00Z"
        Console.WriteLine(dUnspecified.ToUniversalTime().ToString("u"));

        //Prints "2016 - 06 - 01 03:17:00Z"
        Console.WriteLine(dUtc.SafeUniversal().ToString("u"));

        //Prints "2016 - 06 - 01 03:17:00Z"
        Console.WriteLine(dUnspecified.SafeUniversal().ToString("u"));
    }
}

public static class ConvertExtensions
{
    public static DateTime SafeUniversal(this DateTime inTime)
    {
        return (DateTimeKind.Unspecified == inTime.Kind)
            ? new DateTime(inTime.Ticks, DateTimeKind.Utc)
            : inTime.ToUniversalTime();
    }
}

5

Si desidera utilizzare la classe DateTimeOffset .

var date = new DateTimeOffset(2009, 9, 1, 0, 0, 0, 0, new TimeSpan(0L));
var stringDate = date.ToString("u");

scusa mi mancava la tua formattazione originale con i millisecondi

var stringDate = date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

5

Questo codice funziona per me:

var datetime = new DateTime(2017, 10, 27, 14, 45, 53, 175, DateTimeKind.Local);
var text = datetime.ToString("o");
Console.WriteLine(text);
--  2017-10-27T14:45:53.1750000+03:00

// datetime from string
var newDate = DateTime.ParseExact(text, "o", null);

-3

Prova questo:

DateTime date = DateTime.ParseExact(
    "Tue, 1 Jan 2008 00:00:00 UTC", 
    "ddd, d MMM yyyy HH:mm:ss UTC", 
    CultureInfo.InvariantCulture);

Domanda posta in precedenza


3
Non sto cercando di analizzarlo (ancora), sto cercando di stamparlo.
Grzenio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.