web-dev-qa-db-fra.com

Pourquoi ne pas DateTime.Parse analyser la date UTC

Pourquoi ne peut-il pas analyser ceci:

DateTime.Parse("Tue, 1 Jan 2008 00:00:00 UTC")
48
Dve

Il ne peut pas analyser cette chaîne car "UTC" n'est pas un indicateur de fuseau horaire valide.

L’heure UTC est indiquée par l’ajout d’un «Z» à la fin de la chaîne temporelle. Votre code d’analyse doit donc ressembler à ceci:

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

Extrait du Article Wikipedia sur ISO 8601

Si l'heure est en UTC, ajoutez un 'Z' directement après le temps sans un espace. 'Z' est le désignateur de zone pour le décalage zéro UTC. "09:30 UTC" est donc représenté comme "09: 30Z" ou "0930Z". "14:45:15 UTC" serait "14: 45: 15Z" ou "144515Z".

L’heure UTC est également appelée «heure zouloue», puisque 'Zulu' est la phonétique de l'OTAN alphabet Mot pour 'Z'.

66
Simon P Stevens

En supposant que vous utilisiez le format "o" pour votre date/heure, vous avez ainsi "2016-07-24T18: 47: 36Z", il existe un moyen très simple de gérer cela.

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

Lorsque vous appelez DateTime.Parse("2016-07-24T18:47:36Z"), vous obtenez un DateTime défini sur le fuseau horaire local. Donc, il le convertit à l'heure locale. 

La ToUniversalTime() le change en UTC DateTime et le reconvertit en heure UTC.

32
David Thielen

Vous devez spécifier le format:

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

ou utilisez le AdjustToUniversal DateTimeStyle dans un appel à

DateTime.ParseExact(String, String[], IFormatProvider, DateTimeStyles)
12
user213809

Pour analyser correctement la chaîne donnée dans la question sans la changer, utilisez ce qui suit:

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);

Cette implémentation utilise une chaîne pour spécifier le format exact de la chaîne de date analysée. Le paramètre DateTimeStyles est utilisé pour spécifier que la chaîne donnée est une chaîne d'heure universelle coordonnée.

9
satbot

Ce format n'est pas valide, mais "Mardi, 1er janvier 2008 à 00:00:00 GMT" l'est.

La documentation dit comme ceci:

Chaîne contenant des informations sur le fuseau horaire et conforme à la norme ISO 8601. Par exemple, la première des deux chaînes suivantes désigne le temps universel coordonné (UTC); la seconde désigne l'heure dans un fuseau horaire sept heures plus tôt que UTC:

2008-11-01T19: 35: 00.0000000Z 

Chaîne incluant l'indicatif GMT et conforme au format d'heure RFC 1123. Par exemple:

Samedi, 01 novembre 2008 à 19:35:00 GMT

Chaîne contenant la date et l'heure, ainsi que des informations sur le décalage de fuseau horaire. Par exemple:

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

7
HackerBaloo

Il suffit d'utiliser ça:

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!");
}

Vous pouvez tester ce code en utilisant le compilateur en ligne c #:

http://rextester.com/

J'espère que ça aide.

J'ai mis au point une méthode utilitaire qui utilise toutes les astuces présentées ici, ainsi que d'autres:

    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
    }

Remarquez l'utilisation de '-' et de 'T' (une seule citation). Ceci est une pratique exemplaire, car les paramètres régionaux interfèrent avec l’interprétation de caractères tels que "-", ce qui l’interprète comme "/" ou "." ou quels que soient vos paramètres régionaux désignent par date-components-separator. J'ai également inclus une deuxième méthode utilitaire qui montre comment analyser les formats de chaîne de date les plus couramment vus, alimentés par des clients Web pour des applications rest-api. Prendre plaisir.

0
XDS

Il suffit de remplacer "UTC" par "GMT" - simple et ne casse pas les dates correctement formatées:

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