由于在尝试调用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("===");
}
}