web-dev-qa-db-fra.com

c # convertit l'objet datetime en chaîne iso 8601

J'essaie de convertir un objet DateTime en une chaîne ISO8601 mais continue d'obtenir de mauvais résultats. J'ai regardé autour de stackoverflow, mais n'ai pas trouvé la bonne solution. 

Je commence par une chaîne de date/heure de "2017-06-26T20: 45: 00.070Z" qui a été désérialisée par newtonsoft à partir de json et convertie en un objet DateTime en équivalent C #: 

var theTime = new DateTime(2017, 6, 26, 20, 45, 00, 70, DateTimeKind.Utc);

Maintenant, j'ai besoin de la conversion de cette heure en sa chaîne de format UTC d'origine pour l'utiliser dans un autre algorithme, mais chaque conversion que j'essaie ne la renvoie pas à cette chaîne d'origine. Je ne sais pas ce que je fais mal. 

j'ai essayé: 

var newTime = theTime.UtcNow.ToString("o");
// returns "2017-06-26T00:00:00.0000000Z"

var newTime2 = theTime.Date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.sssZ");
// returns "2017-06-26T00:00:00.00Z"

qu'est-ce que je fais mal? Je veux l’équivalent de ce que js fera à l’aide de toISOString (), ce que j’ai répertorié dans le format date-heure newTime2, mais il n’affiche pas les heures non plus. 

merci!

4
user1161137

Observer:

// Your input
DateTime dt = new DateTime(2017, 6, 26, 20, 45, 0, 70, DateTimeKind.Utc);

// ISO8601 with 7 decimal places
string s1 = dt.ToString("o", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.0700000Z"

// ISO8601 with 3 decimal places
string s2 = dt.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.070Z"

Quelques choses:

  • N'utilisez pas Z dans la chaîne de format. Ce n'est pas un spécificateur de format valide , il est donc traité comme un simple caractère à afficher. Ce sera dans chaque chaîne, quel que soit le réglage .Kind de la date/heure d'entrée.

  • Avec DateTime, utilisez K - qui transmet correctement le .Kind en ajoutant un Z à la sortie pour DateTimeKind.Utc ou un décalage par rapport à UTC pour DateTimeKind.Local ou rien du tout pour DateTimeKind.Unspecified.

  • Bien que T apparaisse sous forme de caractère car ce n’est pas un spécificateur de format valide, je suggère d’être toujours explicite à propos de ces choses, donc préférez 'T'.

  • Utiliser fff vous donnera toujours trois décimales (millisecondes). Si vous voulez que les décimales soient omises à zéro, utilisez plutôt FFF. Votre utilisation de sss n'est pas valide.

  • Le passage de CultureInfo.InvariantCulture est une bonne pratique, car il vous aide à éviter les problèmes pour lesquels la culture actuelle pourrait utiliser un système de calendrier différent. Par exemple, ar-SA utilise la variable UmAlQuraCalendar, plutôt que le calendrier proleptique grégorien requis par la norme ISO 8601.

  • Dans votre code que vous avez essayé, vous avez appelé theTime.UtcNow - qui ne compilera pas. UtcNow est une propriété statique, pas une propriété d'instance.

  • Dans votre code, vous avez également appelé theTime.Date.ToUniveralTime() - Ne le faites pas non plus. .Date mettra les composants de temps à zéro et .ToUniversalTime() n'aura aucun effet puisque la valeur d'entrée a déjà DateTimeKind.Utc.

27
Matt Johnson

Le problème est que vous perdez la précision en utilisant une norme culturelle telle que UTC ou UniversalTime. Si vous venez d’imprimer votre DateTime:

var theTime = new DateTime(2017, 6, 26, 20, 45, 00, 70, 
    DateTimeKind.Utc);
Console.WriteLine(theTime);

26/06/2017 20:45:00 PM

Vous pouvez en savoir plus sur ce problème ici .

La solution est de ne pas utiliser de "culture". (Par exemple, UniversalTime ou UtcNow). Ces normes culturelles n'incluent jamais les millisecondes ... car il n'y a pas de culture où les gens se soucient vraiment de la milliseconde.

Solution:

var newTime = theTime.ToString("o");
Console.WriteLine(newTime);

2017-06-26T20: 45: 00.0700000Z

0
Max von Hippel