Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# System.DateTime类位_C#_.net_Datetime - Fatal编程技术网

C# System.DateTime类位

C# System.DateTime类位,c#,.net,datetime,C#,.net,Datetime,由于尝试调用DotNetOAuth加密密钥构造函数时遇到的困难,我开始研究.Net System.DateTime结构。根据我读到的内容,这个对象实际上是由一个64位有符号整数表示的,其中“Ticks”编码在低位62位,而Kind编码在高位2位(注意,它是2位Kind和62位Ticks的串联) 现在我想实际“看到”这一点,所以我构建了一个小型C#程序,创建了三个System.DateTime对象,如下所示: DateTime dtUtc = new System.DateTime(201

由于尝试调用DotNetOAuth加密密钥构造函数时遇到的困难,我开始研究.Net System.DateTime结构。根据我读到的内容,这个对象实际上是由一个64位有符号整数表示的,其中“Ticks”编码在低位62位,而Kind编码在高位2位(注意,它是2位Kind和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属性,正如预期的那样,它们都是相等的。最后,我申请了

这些长时间都是不同的,这也是意料之中的。然而,我随后尝试“检查”上面的两位,以查看哪个状态对应于什么设置,并发现上面的两位在所有三个设置中设置相同。我使用以下例程返回位状态:

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;
}
publicstaticboolisbitset(这个T,int-pos),其中T:struct,IConvertible
{
var值=t.ToInt64(CultureInfo.CurrentCulture);
return(value&(1
ToBinary()
对于不同的
DateTimeKind
工作方式不同。您可以在以下网站上看到它:

public Int64 ToBinary(){
if(Kind==DateTimeKind.Local){
//当您从一个时区移动到另一个时区时,需要调整当地时间,
//就像在文本中序列化时一样。同样,本地时间的格式
//更改以存储UTC时间的节拍,但标记看起来像
//当地日期。
//为了匹配文本中的序列化,我们需要能够处理以下情况:
//UTC值将超出范围。刻度范围中未使用的部分为
//用于此,以便刚刚超过最大值的值存储在刚刚超过
//最大范围的末尾,并且存储刚好低于最小值的值
//在滴答声区域的末尾,略低于2^62。
TimeSpan offset=TimeZoneInfo.GetLocalUtcOffset(这是TimeZoneInfo选项.NoThrowOnInvalidTime);
Int64 ticks=ticks;
Int64 storedTicks=ticks-offset.ticks;
如果(存储的ticks<0){
storedTicks=勾选+storedTicks;
}
返回存储的ticks |(未选中((Int64)LocalMask));
}
否则{
返回(Int64)日期数据;
}
}  
这就是为什么会得到不同的位-本地时间在转换为位之前会进行调整,因此它不再匹配utc时间

这些长度都是不同的,这也是意料之中的。然而,我随后尝试“检查”上面的两位,看看哪个状态对应于什么设置,发现上面的两位在所有三个设置中都设置为相同的

我真的不认为是这样的-ToBinary的结果不是这样的。
ToBinary
。下面是一个简短但完整的程序,使用您的源数据,将结果显示为十六进制(好像未签名):

输出:

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;
}

也许如果我在Jon Skeet的博客上发一个链接,他会神奇地出现。这是他的事。@JonB:这就像在镜子里看着说“Jon Skeet.Jon Skeet.Jon Skeet.”?天哪,你们都很快。就像在离开之前到达的粒子一样。:)让我消化答案,看看我更了解哪个(此时只有两个)。非常感谢。他正在调用
IConvertible
处理从
ToBinary()返回的长变量
public Int64 ToBinary() {
    if (Kind == DateTimeKind.Local) {
        // Local times need to be adjusted as you move from one time zone to another, 
        // just as they are when serializing in text. As such the format for local times
        // changes to store the ticks of the UTC time, but with flags that look like a 
        // local date.

        // To match serialization in text we need to be able to handle cases where
        // the UTC value would be out of range. Unused parts of the ticks range are
        // used for this, so that values just past max value are stored just past the
        // end of the maximum range, and values just below minimum value are stored
        // at the end of the ticks area, just below 2^62.
        TimeSpan offset = TimeZoneInfo.GetLocalUtcOffset(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
        Int64 ticks = Ticks;
        Int64 storedTicks = ticks - offset.Ticks;
        if (storedTicks < 0) {
            storedTicks = TicksCeiling + storedTicks;
        }
        return storedTicks | (unchecked((Int64) LocalMask));
    }
    else {
        return (Int64)dateData;
    }
}  
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
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;
}
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("===");
    }
}