web-dev-qa-db-ja.com

C#の日付時刻を文字列に変換して戻す

C#の日付時刻を文字列に変換しています。後でDateTimeオブジェクトに戻すと、それらは等しくないように見えます。

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

以下に例を示します。日付を印刷すると両方が同じように表示されますが、オブジェクトを比較したり、バイナリ形式で日付を印刷したりすると、すべてが文字列形式に含まれているように見えます。私には奇妙に見えますが、ここで何が起こっているのか説明してもらえますか?

上記のコードの出力は次のとおりです。

-8588633131198276118
634739049656490000
27
axe

roundtripの値を保持する場合は、 DateTime形式指定子「O」または「o」 を使用する必要があります。

「O」または「o」標準形式指定子は、タイムゾーン情報を保持するパターンを使用して、カスタムの日付と時刻の形式文字列を表します。 DateTime値の場合、この形式指定子は、テキストのDateTime.Kindプロパティとともに日付と時刻の値を保持するように設計されています。 stylesパラメーターがDateTimeStyles.RoundtripKindに設定されている場合、DateTime.Parse(String、IFormatProvider、DateTimeStyles)またはDateTime.ParseExactメソッドを使用して、書式設定された文字列を元に戻すことができます。

コードを使用する(フォーマット文字列の変更は別として):

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

私は得る:

-8588633127598789320
-8588633127598789320
40
Oded

Odedの答えは良いのですが、UTCの日付ではうまくいきませんでした。 UTC日付で機能させるために、DateTimeStylesの値を "RoundtripKind"に指定して、現地時間であると想定しようとしないようにする必要がありました。上記の更新されたコードは次のとおりです。

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

これは、UTCとローカル日付の両方で機能します。

8

2つのこと:

  1. AssumeLocalを指定するために、DateTimeStyleパラメーターを受け取るParseExactオーバーロードを使用できます。

  2. 精度を3ではなく7桁に上げない限り、now1とnow2の間にわずかな違いがあります。「yyyy-MM-dd 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());
    

上記の変更がなくても、バイナリ値が類似していないように見えても、now1とnow2の計算された差は小さく見えます。

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

文字列を人間が読めるものにする必要がない場合(たとえば、保存前に暗号化する場合)、string str = dt1.ToBinary().ToString();および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.