问题 DateTime比较内部滴答?


我看了DateTime Equals实现:

public bool Equals(DateTime value)
{
    return (this.InternalTicks == value.InternalTicks);
}

然后看看internalticks

internal long InternalTicks
{
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    get
    {
        return (((long) this.dateData) & 0x3fffffffffffffffL);
    }
}

然后我注意到这个数字: 0x3fffffffffffffffL

这是: 4611686018427387903

更多 有趣的是它 二进制 代表:

00111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
^^
||

请注意箭头

我能理解是否 只有左边 箭就可以了 0 (积极的代表)

  • 但为什么第二个也是 0 ?

  • 另外,为什么我都想要它 & 用一个 1111.... 号码?如果我想要显示 5 我没有必要这样做 5 & 1 ,只有5。

有帮助吗?


5406
2017-11-13 12:20


起源



答案:


你可以从中获得这种信息 参考来源。 dd / ndp / clr / src / bcl / system / datetime.cs中最相关的声明:

    private const UInt64 TicksMask             = 0x3FFFFFFFFFFFFFFF;
    private const UInt64 FlagsMask             = 0xC000000000000000;
    private const UInt64 LocalMask             = 0x8000000000000000;
    private const Int64 TicksCeiling           = 0x4000000000000000;
    private const UInt64 KindUnspecified       = 0x0000000000000000;
    private const UInt64 KindUtc               = 0x4000000000000000;
    private const UInt64 KindLocal             = 0x8000000000000000;
    private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
    private const Int32 KindShift = 62;

注意如何  值映射到这两个位。

    public DateTime(long ticks, DateTimeKind kind) {
        // Error checking omitted
        //...
        this.dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
    }

7
2017-11-13 12:27



所以在左边放两个零(2个零)就像比较没有DateTimeKind ......对吗? - Royi Namir
对。它是一个 面具,使用&运算符屏蔽这些位的值并使它们为零。 - Hans Passant
@RoyiNamir是的,它忽略了 Kind 比较掩盖它。 (错误的决定IMO) - CodesInChaos
@CodesInChaos所以你比较时间时只在你的c#中使用DateTimeOffset? - Royi Namir


答案:


你可以从中获得这种信息 参考来源。 dd / ndp / clr / src / bcl / system / datetime.cs中最相关的声明:

    private const UInt64 TicksMask             = 0x3FFFFFFFFFFFFFFF;
    private const UInt64 FlagsMask             = 0xC000000000000000;
    private const UInt64 LocalMask             = 0x8000000000000000;
    private const Int64 TicksCeiling           = 0x4000000000000000;
    private const UInt64 KindUnspecified       = 0x0000000000000000;
    private const UInt64 KindUtc               = 0x4000000000000000;
    private const UInt64 KindLocal             = 0x8000000000000000;
    private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
    private const Int32 KindShift = 62;

注意如何  值映射到这两个位。

    public DateTime(long ticks, DateTimeKind kind) {
        // Error checking omitted
        //...
        this.dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
    }

7
2017-11-13 12:27



所以在左边放两个零(2个零)就像比较没有DateTimeKind ......对吗? - Royi Namir
对。它是一个 面具,使用&运算符屏蔽这些位的值并使它们为零。 - Hans Passant
@RoyiNamir是的,它忽略了 Kind 比较掩盖它。 (错误的决定IMO) - CodesInChaos
@CodesInChaos所以你比较时间时只在你的c#中使用DateTimeOffset? - Royi Namir


dateData 字段用作a 比特场 以紧凑格式存储多个值。

前两位存储 DateTimeKind,它有四个可能的值之一:Unspecified,Local(内部有两个变体)或Utc。这四个值可以存储为两位。

底部62位存储刻度线。操作 x & 0x3fffffffffffffffL 是一个按位和操作,有时也称为 掩蔽。它仅返回与刻度对应的位。


4
2017-11-13 12:22



在内部它实际上有4个不同的值。有两种不同的变体 Local 它与DST切换的交互方式不同。 - CodesInChaos
请看我的编辑 - 它没有附加值。 - Royi Namir
@RoyiNamir我不明白你的编辑想说什么,但Mark的回答是正确的。 - CodesInChaos
@CodesInChaos汉斯已经在他的回答中展示了它。例如 - 我不知道UTC的值是x,而LOCAL的值是Y - 我认为它应该在枚举中。但它写在另一个地方。 - Royi Namir
@MarkByers有很多在.net中有价值的枚举。(不是全部......我只是用反射器搜索了一些,有些有值,有些则没有)。如果未来的版本添加了一个元素,他们可以附加一个值而不是替换....不? - Royi Namir