web-dev-qa-db-fra.com

convertir la date et l'heure C # en chaîne et en retour

Je convertis l'heure de date C # en chaîne. Plus tard, lorsque je le reconvertirai en DateTime object, il apparaît qu'ils ne sont pas égaux.

const string FMT = "yyyy-MM-dd HH:mm:ss.fff";
DateTime now1 = DateTime.Now;
string strDate = now1.ToString(FMT);
DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture);
Console.WriteLine(now1.ToBinary());
Console.WriteLine(now2.ToBinary());

Voici l'exemple. On dirait que tout est inclus dans le format de chaîne, lorsque j'imprime la date, les deux affichent la même chose, mais lorsque je compare des objets ou que j'imprime la date au format binaire, je vois la différence. Cela me semble étrange, pourriez-vous s'il vous plaît expliquer ce qui se passe ici?

Voici la sortie pour le code ci-dessus.

-8588633131198276118
634739049656490000
27
axe

Vous devez utiliser le spécificateur de format roundtrip "O" ou "o" si vous souhaitez conserver la valeur de DateTime.

Le spécificateur de format standard "O" ou "o" représente une chaîne de format de date et d'heure personnalisée à l'aide d'un modèle préservant les informations de fuseau horaire. Pour les valeurs DateTime, ce spécificateur de format est conçu pour conserver les valeurs de date et d'heure, ainsi que la propriété DateTime.Kind dans le texte. La méthode mise en forme peut être analysée à l'aide de la méthode DateTime.Parse (String, IFormatProvider, DateTimeStyles) ou DateTime.ParseExact si le paramètre styles est défini sur DateTimeStyles.RoundtripKind.

En utilisant votre code (en dehors de changer la chaîne de format):

const string FMT = "O";
DateTime now1 = DateTime.Now;
string strDate = now1.ToString(FMT);
DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture);
Console.WriteLine(now1.ToBinary());
Console.WriteLine(now2.ToBinary());

Je reçois:

-8588633127598789320
-8588633127598789320
39
Oded

La réponse d'Oded est bonne mais cela n'a pas fonctionné pour moi pour les dates UTC. Afin de le faire fonctionner pour les dates UTC, je devais spécifier une valeur DateTimeStyles de "RoundtripKind" afin qu'elle n'essaye pas de supposer qu'il s'agit d'une heure locale. Voici le code mis à jour ci-dessus:

const string FMT = "O";
DateTime now1 = DateTime.Now;
string strDate = now1.ToString(FMT);
DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
Console.WriteLine(now1.ToBinary());
Console.WriteLine(now2.ToBinary());

Notez que cela fonctionne pour les dates UTC et locales.

7
Taylor Lafrinere

2 choses:

  1. Vous pouvez utiliser la surcharge ParseExact qui prend un paramètre DateTimeStyle afin de spécifier AssumeLocal.

  2. Il y aura toujours une petite différence entre now1 et now2 sauf si vous augmentez la précision à 7 chiffres au lieu de 3: "aaaa-MM-jj HH: mm: ss.fffffff"

        const string FMT = "yyyy-MM-dd HH:mm:ss.fffffff";
        DateTime now1 = DateTime.Now;
        string strDate = now1.ToString(FMT);
        DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
        Console.WriteLine(now1.ToBinary());
        Console.WriteLine(now2.ToBinary());
    

Même sans les modifications ci-dessus, la différence calculée entre now1 et now2 semble faible, même si les valeurs binaires n'apparaissent pas similaires.

        TimeSpan difference = now2.Subtract(now1);
        Console.WriteLine(difference.ToString());
1

Si vous n'avez pas besoin que la chaîne soit lisible par l'homme (comme vous voulez la chiffrer avant le stockage), vous pouvez simplement appeler string str = dt1.ToBinary().ToString(); et DateTime dt2 = DateTime.FromBinary(long.Parse(str));.

DateTime now1 = DateTime.Now;
string strDate = now1.ToBinary().ToString();
DateTime now2 = DateTime.FromBinary(long.Parse(strDate));
Console.WriteLine(now1.ToBinary());
Console.WriteLine(now2.ToBinary());
0
Jan 'splite' K.