none
DateTime.Now.ToBinary()について RRS feed

  • 質問

  • いつもお世話になっております。
    DateTime.Now.ToBinary()について、
    予想外の動きをしたため、質問させていただきたく思います。
    以下のコードではn,n2は同じ値を示しますが、
    d1,d2はものすごくかけ離れた値を示しています。
    今までDateTimeの数値表現は線形対応していると
    思って作っていたのですが、そうではないのでしょうか。
    また、DateTime.Nowは何か特別な存在なのでしょうか。

    現在ToBinaryの値でいろいろなところで比較を行っているため、
    DateTime.Nowを直接使わないように変更すればバグは直りそうなのですが
    そんな対応でよいのでしょうか。
    宜しくお願い致します。



       DateTime n = DateTime.Now;
       DateTime n2 = new DateTime( n.Year, n.Month, n.Day, n.Hour, n.Minute, n.Second, n.Millisecond );

       long d1 = n.ToBinary();
       long d2 = n2.ToBinary();

       n = DateTime.FromBinary( d1 );
       n2 = DateTime.FromBinary( d2 );

    2009年6月4日 2:54

回答

  • ToBinary の返値の解説に「Kind プロパティおよび Ticks プロパティをエンコードする 64 ビットの符号付き整数。」とあるように、ToBinary は Kind プロパティも考慮してエンコードされます。

    DateTime.Now は解説に明記されているように Local 時刻を返しますが、コンストラクタで初期化した場合、Kind を明示しなければ Unspecified 時刻で生成されることになります。当然、ToBinary のエンコード結果も異なる値になります。

    なお、DateTime が保持する最小単位は 100 ns です。ミリ秒までを指定してコンストラクタで初期化する場合、マイクロ秒以下が切り捨てられる可能性があることに注意してください。DateTime.Now は NT 系での近似解像度は 10ms となってますが、特にミリ秒単位に丸めるとの記述もないですし。

    今までDateTimeの数値表現は線形対応していると思って作っていたのですが、そうではないのでしょうか。

    ドキュメントにどうエンコードするのか記述されていない以上、そんなのが保証されるわけはありません。

    • 回答の候補に設定 kassyi 2009年6月6日 7:44
    • 回答としてマーク sk7474 2009年6月19日 8:49
    2009年6月4日 3:49
  • 補足で
    DateTime n2 = new DateTime( n.Year, n.Month, n.Day, n.Hour, n.Minute, n.Second, n.Millisecond, n.Kind );
    とすれば近い値になると思います。ミリ秒以下の分解能限界まで意識する場合は、Ticksプロパティ(+Kindプロパティ)を使えます。
    • 回答としてマーク sk7474 2009年6月19日 8:49
    2009年6月4日 9:46

すべての返信

  • ToBinary の返値の解説に「Kind プロパティおよび Ticks プロパティをエンコードする 64 ビットの符号付き整数。」とあるように、ToBinary は Kind プロパティも考慮してエンコードされます。

    DateTime.Now は解説に明記されているように Local 時刻を返しますが、コンストラクタで初期化した場合、Kind を明示しなければ Unspecified 時刻で生成されることになります。当然、ToBinary のエンコード結果も異なる値になります。

    なお、DateTime が保持する最小単位は 100 ns です。ミリ秒までを指定してコンストラクタで初期化する場合、マイクロ秒以下が切り捨てられる可能性があることに注意してください。DateTime.Now は NT 系での近似解像度は 10ms となってますが、特にミリ秒単位に丸めるとの記述もないですし。

    今までDateTimeの数値表現は線形対応していると思って作っていたのですが、そうではないのでしょうか。

    ドキュメントにどうエンコードするのか記述されていない以上、そんなのが保証されるわけはありません。

    • 回答の候補に設定 kassyi 2009年6月6日 7:44
    • 回答としてマーク sk7474 2009年6月19日 8:49
    2009年6月4日 3:49
  • 補足で
    DateTime n2 = new DateTime( n.Year, n.Month, n.Day, n.Hour, n.Minute, n.Second, n.Millisecond, n.Kind );
    とすれば近い値になると思います。ミリ秒以下の分解能限界まで意識する場合は、Ticksプロパティ(+Kindプロパティ)を使えます。
    • 回答としてマーク sk7474 2009年6月19日 8:49
    2009年6月4日 9:46
  • HongLiang様、佐祐理様
    ご回答ありがとうございました。

    Kindというプロパティを知らなかったのですが、
    この情報も一緒に入るのですね。
    納得いたしました。

    2009年6月5日 10:31
  • こんにちは。中川俊輔です。

    Hongliangさん、佐祐理さん、詳しい回答ありがとうございます。

    Myonさん、フォーラムのご利用ありがとうございます。
    有用な情報と思われたため、勝手ながらHongliangさん、佐祐理さんの回答へ回答マークをつけさせていただきました。

    今後ともフォーラムをよろしくお願いします。
    それでは!
    マイクロソフト株式会社 フォーラム オペレータ 中川 俊輔
    2009年6月19日 8:51