由于在尝试调用dotnetoauth密钥构造函数时遇到的困难,我开始研究.net system.datetime结构。根据我读到的,这个对象实际上是由一个64位有符号整数表示的,其中“ticks”编码在下面的62位,种类编码在上面的2位(low,它是2位种类和62位ticks的连接)。
现在我想“看到”这个,所以我构造了一个小的C程序,它创建了三个System.DateTime对象:

    DateTime dtUtc = new System.DateTime(2014, 4, 29, 9, 10, 30, System.DateTimeKind.Utc);
    DateTime dtLocal = new System.DateTime(2014, 4, 29, 9, 10, 30, System.DateTimeKind.Local);
    DateTime dtU = new System.DateTime(2014, 4, 29, 9, 10, 30, System.DateTimeKind.Unspecified);

然后,我为每个对象都转储了ticks属性,正如预期的那样,它们都是相等的。最后,我申请了。
    long bitUtc = dtUtc.ToBinary();
    long bitLocal = dtLocal.ToBinary();
    long bitU = dtU.ToBinary();

这些长的都不一样了,正如预期的那样。然而,我试图“检查”上面的两个位,看看哪个状态对应于什么设置,发现上面的两个位在这三个设置中都是一样的。我使用以下例程返回位状态:
public static bool IsBitSet<T>(this T t, int pos) where T : struct, IConvertible
{
    var value = t.ToInt64(CultureInfo.CurrentCulture);
    return (value & (1 << pos)) != 0;
}

(我是从另一个帖子上得知的),并这样称呼它:
    Boolean firstUtc = Class1.IsBitSet<long>(bitUtc, 63);
    Boolean secondUtc = Class1.IsBitSet<long>(bitUtc, 62);
    Boolean firstLocal = Class1.IsBitSet<long>(bitLocal, 63);
    Boolean secondLocal = Class1.IsBitSet<long>(bitLocal, 62);
    Boolean firstU = Class1.IsBitSet<long>(bitU, 63);
    Boolean secondU = Class1.IsBitSet<long>(bitU, 62);

同样,第一位和第二位在所有三位中设置相同(第一位为真,第二位为假)。我不明白这一点,因为我认为这些都是不同的,对应于不同的systemkind值。
最后,我做了更多的阅读,发现(或者至少在一个源代码中说过)ms没有序列化.tobinary()中的种类信息。好吧,那为什么.tobinary()方法的输出都不一样呢?
如果有人能给我指点方向,让我知道哪里出错了,我会非常感激。

最佳答案

这些长的都不一样了,正如预期的那样。然而,我试图“检查”上面的两个位,看看哪个状态对应于什么设置,发现上面的两个位在这三个设置中都是一样的。
我真的不认为这是事实-不是与ToBinary的结果。下面是一个简短但完整的程序,使用源数据演示了差异,结果显示为十六进制(好像没有符号):

using System;

class Test
{
    static void Main()
    {
        DateTime dtUtc = new System.DateTime(2014, 4, 29, 9, 10, 30, System.DateTimeKind.Utc);
        DateTime dtLocal = new System.DateTime(2014, 4, 29, 9, 10, 30, System.DateTimeKind.Local);
        DateTime dtU = new System.DateTime(2014, 4, 29, 9, 10, 30, System.DateTimeKind.Unspecified);
        Console.WriteLine(dtUtc.ToBinary().ToString("X16"));
        Console.WriteLine(dtLocal.ToBinary().ToString("X16"));
        Console.WriteLine(dtU.ToBinary().ToString("X16"));
    }
}

输出:
48D131A200924700
88D131999ECDDF00
08D131A200924700

前两位分别是01、10和00。根据marcin的文章,其他的位也会因本地情况而改变,但前两位确实表明了这一类型。
IsBitSet方法被破坏,因为它左移了一个int文本而不是一个long文本。这意味着这个转变将是mod 32,而不是mod 64。请改为:
public static bool IsBitSet<T>(this T t, int pos) where T : struct, IConvertible
{
    var value = t.ToInt64(CultureInfo.CurrentCulture);
    return (value & (1L << pos)) != 0;
}

最后,我做了更多的阅读,发现(或者至少在一个源代码中说过)ms没有序列化.tobinary()中的种类信息。
很容易证明这不是真的:
using System;

class Test
{
    static void Main()
    {
        DateTime start = DateTime.UtcNow;
        Show(DateTime.SpecifyKind(start, DateTimeKind.Utc));
        Show(DateTime.SpecifyKind(start, DateTimeKind.Local));
        Show(DateTime.SpecifyKind(start, DateTimeKind.Unspecified));
    }

    static void Show(DateTime dt)
    {
        Console.WriteLine(dt.Kind);
        DateTime dt2 = DateTime.FromBinary(dt.ToBinary());
        Console.WriteLine(dt2.Kind);
        Console.WriteLine("===");
    }
}

10-07 19:47