DateTime.ToString ("MM / jj / aaaa HH: mm: ss.fff") a généré quelque chose comme "14/09/2013 20.07.31.371"

131

J'ai une application WP8, qui enverra l'heure actuelle à un service Web.

J'obtiens la chaîne datetime en appelant

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff")

Pour la plupart des utilisateurs, cela fonctionne très bien et me donne la chaîne correcte comme "09/10/2013 04:04:31.415". Mais pour certains utilisateurs, la chaîne résultante est quelque chose comme "09/14/2013 07.20.31.371", ce qui pose problème dans mon service Web.

Est-ce à cause d'un problème de format culturel? Comment puis-je m'assurer que la chaîne de résultat est délimitée par deux points au lieu d'un point?

Eldorado
la source
2
la seule différence est deux points par rapport au point.
Eldorado
Reportez-vous à .Net Standard 2 samples
Sina Lotfi

Réponses:

244

Est-ce à cause d'un problème de format culturel?

Oui. Votre utilisateur doit appartenir à une culture où le séparateur d'heure est un point. Les deux ":" et "/" sont interprétés d'une manière sensible à la culture dans des formats de date et d'heure personnalisés .

Comment puis-je m'assurer que la chaîne de résultat est délimitée par deux points au lieu d'un point?

Je suggère de préciser CultureInfo.InvariantCulture:

string text = dateTime.ToString("MM/dd/yyyy HH:mm:ss.fff",
                                CultureInfo.InvariantCulture);

Alternativement, vous pouvez simplement citer les séparateurs d'heure et de date:

string text = dateTime.ToString("MM'/'dd'/'yyyy HH':'mm':'ss.fff");

... mais cela vous donnera des résultats "intéressants" auxquels vous ne vous attendez probablement pas si vous faites fonctionner des utilisateurs dans une culture où le système de calendrier par défaut n'est pas le calendrier grégorien. Par exemple, prenez le code suivant:

using System;
using System.Globalization;
using System.Threading;

class Test
{
    static void Main()        
    {
        DateTime now = DateTime.Now;
        CultureInfo culture = new CultureInfo("ar-SA"); // Saudi Arabia
        Thread.CurrentThread.CurrentCulture = culture;
        Console.WriteLine(now.ToString("yyyy-MM-ddTHH:mm:ss.fff"));
    }
} 

Cela produit la sortie (le 18 septembre 2013) de:

11/12/1434 15:04:31.750

Je suppose que votre service Web en serait surpris!

Je suggérerais en fait non seulement d'utiliser la culture invariante, mais également de passer à un format de date ISO-8601:

string text = dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");

Il s'agit d'un format plus accepté dans le monde entier - il est également triable et rend l'ordre du mois et du jour évident. (Alors que le 06/07/2013 pourrait être interprété comme le 7 juin ou le 6 juillet selon la culture du lecteur.)

Jon Skeet
la source
merci Jon. Je pensais que la chaîne de résultat serait exactement comme la chaîne de format. J'essaierai votre suggestion.
Eldorado
3
Juste une petite considération. Lors du chargement d'un objet CultureInfo à partir d'un code spécifique, je suggère toujours de définir le useUserOverrideparamètre sur false, sinon certains paramètres utilisateur peuvent remplacer les paramètres de culture. Par exemple dans votre cas, je suggère d'utiliser new CultureInfo("ar-SA", false).
Davide Icardi
@DavideIcardi: Intéressant, merci - bien que dans ce cas, le but de l'utilisation de l'Arabie saoudite était spécifiquement de dire pourquoi l'utilisation de la culture invariante est probablement juste. Je garderai cela à l'esprit pour les prochains articles.
Jon Skeet
7
À mi-chemin de cette longue réponse, j'ai commencé à me demander: serait-ce à nouveau Jon? Oui.
Grimace of Despair
Comment gérer la même chose avec Html.TextBoxFor (x => x.Date, "{0: MM / dd / yyyy}")?
VISHMAY
9

:a une signification particulière: c'est le séparateur de temps. ( Chaînes de format de date et d'heure personnalisées ).

Utilisez \pour y échapper:

DateTime.ToString(@"MM/dd/yyyy HH\:mm\:ss.fff")

Ou utilisez CultureInfo.InvariantCulture:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture)

Je suggérerais d'aller avec le deuxième, car il /a également une signification particulière (c'est le séparateur de date. ), Vous pouvez donc avoir des problèmes avec cela aussi.

MarcinJuraszek
la source
2
Ce n'est pas seulement le séparateur de date qui pose problème - voir ma réponse pour un exemple de la culture affectant les chiffres réels, aussi ...
Jon Skeet
1
\ n'y échappe pas!
Shereef Marzouk le
8

Vous pouvez utiliser InvariantCulture car votre utilisateur doit être dans une culture qui utilise un point au lieu d'un deux-points:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture);
Jon La Marr
la source
7

Je suis tombé sur ce problème récemment avec Windows 10 dans une autre direction et j'ai trouvé la réponse de @JonSkeet très utile pour résoudre mon problème.

J'ai également fait quelques recherches supplémentaires avec un formulaire de test et j'ai constaté que lorsque la culture actuelle était définie sur "no"ou "nb-NO"à l'exécution ( Thread.CurrentThread.CurrentCulture = new CultureInfo("no");), l'appel ToString ("aaaa-MM-jj HH: mm: ss") répondait différemment dans Windows 7 et Windows 10. Il a renvoyé ce que j'attendais dans Windows 7 et HH.mm.ss dans Windows 10!

Je pense que c'est un peu effrayant! Depuis que je croyais qu'une culture était une culture dans n'importe quelle version de Windows au moins.

Håkon Seljåsen
la source
Je serais assez curieux de savoir ce qui cause vraiment cela.
Lauri Peltonen
2
Il a été reconnu et corrigé en tant que bogue de localisation Windows 10. Ainsi, une mise à jour de Windows sur l'ordinateur client résoudra le problème. Plus de détails sont disponibles dans ce billet de blog: heikniemi.net/hardcoded/2015/08/…
Håkon Seljåsen
Le blog de Jouni Heikniemi, auquel j'ai lié ci-dessus, semble être cassé. Les mises à jour Windows pertinentes où les problèmes ont été résolus y étaient répertoriées: 09/10/2015: KB3093266 - Windows 10 KB3088956 - Windows Server 2012 R2 et Windows 8.1 KB3088955 - Windows Server 2012 et Windows 8 KB3088957 - Windows 7 SP1, Windows Server 2008 SP2 , Windows Server 2008 R2 SP1 et Windows Vista SP2
Tentative de création
4

Vous pouvez utiliser String.Format:

DateTime d = DateTime.Now;
string str = String.Format("{0:00}/{1:00}/{2:0000} {3:00}:{4:00}:{5:00}.{6:000}", d.Month, d.Day, d.Year, d.Hour, d.Minute, d.Second, d.Millisecond);
// I got this result: "02/23/2015 16:42:38.234"
Cosmin
la source
0

Convertir la date en chaîne

Utiliser l'espace de nom

using System.Globalization;

Code

string date = DateTime.ParseExact(datetext.Text, "dd-MM-yyyy", CultureInfo.InstalledUICulture).ToString("yyyy-MM-dd");
Hafsal
la source
Ce n'est pas comment convertir une date en chaîne. L'analyse est l'inverse!
Vincent Vancalbergh