Warum kann DateTime.Parse das UTC-Datum nicht analysieren?

74

Warum kann es das nicht analysieren:

DateTime.Parse("Tue, 1 Jan 2008 00:00:00 UTC")
Dve
quelle
3
IE9 fügt immer noch fälschlicherweise "UTC" hinzu, wenn Sie new Date().toUTCString()in Javascript
Chris S
Für alle, die zu diesem Beitrag 2009 kommen, ist die Antwort auf dieses Problem momentjs.com
Liam

Antworten:

88

Diese Zeichenfolge kann nicht analysiert werden, da "UTC" kein gültiger Zeitzonenbezeichner ist.

Die UTC-Zeit wird durch Hinzufügen eines 'Z' am Ende der Zeitzeichenfolge angegeben. Ihr Parsing-Code sollte also folgendermaßen aussehen:

DateTime.Parse("Tue, 1 Jan 2008 00:00:00Z");

Aus dem Wikipedia-Artikel zu ISO 8601

Wenn die Zeit in UTC ist, fügen Sie direkt nach der Zeit ohne Leerzeichen ein 'Z' hinzu. 'Z' ist die Zonenbezeichnung für den Null-UTC-Offset. "09:30 UTC" wird daher als "09: 30Z" oder "0930Z" dargestellt. "14:45:15 UTC" wäre "14: 45: 15Z" oder "144515Z".

Die UTC-Zeit wird auch als "Zulu" -Zeit bezeichnet, da "Zulu" das phonetische Alphabet der NATO für "Z" ist.

Simon P Stevens
quelle
1
Die Datumszeichenfolge in meinem Beispiel stammt vom Internet Explorer
Dve
@ Dave: Wenn Sie sagen, dass es vom IE stammt, meinen Sie damit, dass Sie es von einer Webseite extrahiert haben? Möglicherweise müssen Sie Ihren eigenen Ersatz für den DateTime-Parser schreiben, der die UTC extrahiert und durch einen Z ersetzt.
Simon P Stevens
Nachdem ich gegen FF getestet hatte, hatte ich vergessen, dass ich die toUTCString () -Methode an dem Datum aufgerufen hatte, an dem ich sie auf den Server zurückschickte. FF sendet GMT, während IE UTC sendet. Also kann ich IE nicht beschuldigen ... diesmal!
Dve
67
Wie andere Antworten zeigen, würde die UTC-Datumszeichenfolge mit dem Z-Bezeichner zwar erfolgreich analysiert , aber auch in die Ortszeit konvertiert, dh DateTimemit einem Kindvon Localund einem angepassten Zeitstempel zurückgegeben. Um immer UTC zu erhalten DateTime, kann man eines verwenden DateTime.Parse("2008-01-01 00:00:00Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal), wie @crokusek vorschlägt, oder DateTimeOffset.Parse("2008-01-01 00:00:00Z").UtcDateTime, wie @ruffin vorschlägt.
Sergii Volchkov
Ist es in Meta-Tags wie http-equiv="last-modified"dem Format 2013-10-23 @ 17: 23: 00 UTC möglich?
PreguntonCojoneroCabrón
64

Angenommen, Sie verwenden das Format "o" für Ihre Datumszeit, sodass Sie "2016-07-24T18: 47: 36Z" haben, gibt es eine sehr einfache Möglichkeit, dies zu handhaben.

Rufen Sie an DateTime.Parse("2016-07-24T18:47:36Z").ToUniversalTime().

Wenn Sie anrufen, erhalten DateTime.Parse("2016-07-24T18:47:36Z")Sie eine DateTimeEinstellung für die lokale Zeitzone. Es konvertiert es also in die Ortszeit.

Das ToUniversalTime()ändert es in eine UTC DateTimeund konvertiert es zurück in die UTC-Zeit.

David Thielen
quelle
Angenommen, dies passiert, wenn Sie ein Zulu an eine Web-API gesendet haben und es dennoch als Ortszeit angezeigt wird. Ich denke, etwas hat gerade geklickt, danke
Andrew
26

Verwenden Sie einfach das:

var myDateUtc = DateTime.SpecifyKind(DateTime.Parse("Tue, 1 Jan 2008 00:00:00"), DateTimeKind.Utc);

if (myDateUtc.Kind == DateTimeKind.Utc)
{
     Console.WriteLine("Yes. I am UTC!");
}

Sie können diesen Code mit dem Online-C # -Compiler testen:

http://rextester.com/

Ich hoffe, es hilft.

Ricardo de Assuncao Goncalves
quelle
18

Sie müssen das Format angeben:

DateTime date = DateTime.ParseExact(
    "Tue, 1 Jan 2008 00:00:00 UTC", 
    "ddd, d MMM yyyy HH:mm:ss UTC", 
    CultureInfo.InvariantCulture);
Darin Dimitrov
quelle
2
Netter Vorschlag, aber dies würde fehlschlagen, wenn die angegebene Datumszeichenfolge am Ende keine UTC enthalten würde. Angenommen, Sie haben stattdessen eine Datumszeichenfolge mit +01 am Ende übergeben, was zu einer FormatException führen würde. Kommt darauf an, was er versucht, nehme ich an.
Simon P Stevens
17

oder verwenden Sie den AdjustToUniversal DateTimeStyle in einem Aufruf von

DateTime.ParseExact(String, String[], IFormatProvider, DateTimeStyles)
user213809
quelle
5
Das funktioniert tatsächlich. Ich habe diesen Code verwendet und die korrekte UTC DateTime aus der UTC-Zeichenfolge erhalten: DateTime.TryParseExact ("2012-01-30T00: 28: 00Z", "JJJJ-MM-TTTHH: MM: SSZ", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out Zeitwert));
Roboblob
21
Dies funktioniert auch, Utc rein und raus, kein Format, kein Z erforderlich: DateTime.Parse ("03.08.2013 01:02:41", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
Crokusek
Ich habe es mit einer UTC-Zeitzeichenfolge zu tun, die Roboblob ähnelt, und einen Code verwendet, der dem von Roboblob angegebenen ähnlich ist, um die UTC-Ness des Werts beizubehalten: DateTime.ParseExact (utcTimeStringINeededToParse, "yyyy-MM-ddTHH: mm: ss.0000000Z", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AdjustToUniversal)
StackOverflowUser
10

Verwenden Sie Folgendes, um die in der Frage angegebene Zeichenfolge korrekt zu analysieren, ohne sie zu ändern:

using System.Globalization;

string dateString = "Tue, 1 Jan 2008 00:00:00 UTC";
DateTime parsedDate = DateTime.ParseExact(dateString, "ddd, d MMM yyyy hh:mm:ss UTC", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal);

Diese Implementierung verwendet eine Zeichenfolge, um das genaue Format der Datumszeichenfolge anzugeben, die analysiert wird. Der Parameter DateTimeStyles wird verwendet, um anzugeben, dass die angegebene Zeichenfolge eine koordinierte universelle Zeitzeichenfolge ist.

Satbot
quelle
Laut den Dokumenten ist "die KindEigenschaft des zurückgegebenen DateTimeWertes DateTimeKind.Local". ParseExact analysiert es korrekt als UTC, konvertiert es dann jedoch in die Ortszeit, bevor es zurückgegeben wird. Verwenden DateTimeStyles.RoundtripKindSie diese Option, wenn der zurückgegebene Wert unverändert als UTC zurückgegeben werden soll.
Daniel Schilling
7

Es ist kein gültiges Format, jedoch "Di, 1. Januar 2008 00:00:00 GMT".

Die Dokumentation sagt so:

Eine Zeichenfolge, die Zeitzoneninformationen enthält und ISO 8601 entspricht. Beispielsweise bezeichnet die erste der folgenden beiden Zeichenfolgen die koordinierte Weltzeit (UTC). Die zweite bezeichnet die Zeit in einer Zeitzone sieben Stunden vor UTC:

2008-11-01T19: 35: 00.0000000Z

Eine Zeichenfolge, die den GMT-Bezeichner enthält und dem RFC 1123-Zeitformat entspricht. Zum Beispiel:

Sa, 01. November 2008 19:35:00 GMT

Eine Zeichenfolge, die Datum und Uhrzeit sowie Informationen zum Zeitzonenversatz enthält. Zum Beispiel:

03/01/2009 05:42:00 -5: 00

HackerBaloo
quelle
Ein einfaches Ersetzen von "UTC" durch "GMT" in einer Datumszeichenfolge ähnlich diesem Format funktioniert hervorragend, danke für den Tipp.
James Wilkins
1
Beachten Sie jedoch, dass dies ein DateTimemit einem Kindvon Localfür mich zurückgibt . Es sieht so aus, als ob die Problemumgehung darin besteht, DateTimeOffset.Parse (und dann x.UtcDateTime) zu verwenden, wenn Sie sicherstellen möchten, dass Sie während der Analyse nicht vom UTC-Wagen fallen.
Ruffin
1

Ersetzen Sie einfach "UTC" durch "GMT" - einfach und bricht nicht korrekt formatierte Daten:

DateTime.Parse("Tue, 1 Jan 2008 00:00:00 UTC".Replace("UTC", "GMT"))
Mike Godin
quelle
1

Ich habe eine Dienstprogrammmethode zusammengestellt, die alle hier gezeigten Tipps und einige weitere verwendet:

    static private readonly string[] MostCommonDateStringFormatsFromWeb = {
        "yyyy'-'MM'-'dd'T'hh:mm:ssZ",  //     momentjs aka universal sortable with 'T'     2008-04-10T06:30:00Z          this is default format employed by moment().utc().format()
        "yyyy'-'MM'-'dd'T'hh:mm:ss.fffZ", //  syncfusion                                   2008-04-10T06:30:00.000Z      retarded string format for dates that syncfusion libs churn out when invoked by ejgrid for odata filtering and so on
        "O", //                               iso8601                                      2008-04-10T06:30:00.0000000
        "s", //                               sortable                                     2008-04-10T06:30:00
        "u"  //                               universal sortable                           2008-04-10 06:30:00Z
    };

    static public bool TryParseWebDateStringExactToUTC(
        out DateTime date,
        string input,
        string[] formats = null,
        DateTimeStyles? styles = null,
        IFormatProvider formatProvider = null
    )
    {
        formats = formats ?? MostCommonDateStringFormatsFromWeb;
        return TryParseDateStringExactToUTC(out date, input, formats, styles, formatProvider);
    }

    static public bool TryParseDateStringExactToUTC(
        out DateTime date,
        string input,
        string[] formats = null,
        DateTimeStyles? styles = null,
        IFormatProvider formatProvider = null
    )
    {
        styles = styles ?? DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal; //0 utc
        formatProvider = formatProvider ?? CultureInfo.InvariantCulture;

        var verdict = DateTime.TryParseExact(input, result: out date, style: styles.Value, formats: formats, provider: formatProvider);
        if (verdict && date.Kind == DateTimeKind.Local) //1
        {
            date = date.ToUniversalTime();
        }

        return verdict;

        //0 employing adjusttouniversal is vital in order for the resulting date to be in utc when the 'Z' flag is employed at the end of the input string
        //  like for instance in   2008-04-10T06:30.000Z
        //1 local should never happen with the default settings but it can happen when settings get overriden   we want to forcibly return utc though
    }

Beachten Sie die Verwendung von '-' und 'T' (in einfachen Anführungszeichen). Dies geschieht als bewährte Methode, da regionale Einstellungen die Interpretation von Zeichen wie '-' beeinträchtigen und dazu führen, dass sie als '/' oder 'interpretiert werden. oder was auch immer Ihre regionalen Einstellungen als Datums-Komponenten-Trennzeichen bezeichnen. Ich habe auch eine zweite Dienstprogrammmethode hinzugefügt, die zeigt, wie die am häufigsten verwendeten Datumszeichenfolgenformate analysiert werden, die von Web-Clients an Rest-API-Backends gesendet werden. Genießen.

XDS
quelle
-4

Ich weiß nicht warum, aber Sie können DateTime.ToUniversalTime in einen Versuch / Fang einschließen und das gleiche Ergebnis in mehr Code erzielen.

Viel Glück.

Ian P.
quelle
ToUniversalTime wirft nie eine Ausnahme
porges