如何使用C#中的DateTime.Now.Ticks保持精度

时间:2010-04-22 22:55:59

标签: c# .net datetime timestamp

我知道当我在C#中使用DateTime.Now.Ticks时它会返回一个long值,但是我需要将它存储在一个int变量中,我对是否能保持这种精度感到困惑。截至目前我只是有一个演员

int timeStampValue = (int)DateTime.Now.Ticks;

这是一个项目约束,所以我知道有很多精度损失。我想我只是想不出另一种方法来存储一个存储在int中的时间戳,然后我可以将其与其他时间戳进行比较。

如果可能的话,任何关于如何保持精确度的建议或建议将非常感激。

每个人的答案都是说明性的。我实际上最终只设置了一个涉及计数器的进程,当使用一个项目时,它的计数器设置为'0',所有其他计数器增加1.然后,最高计数器是下一个要使用的项目。

5 个答案:

答案 0 :(得分:13)

DateTime.Now并不是那么准确。

http://blogs.msdn.com/ericlippert/archive/2010/04/08/precision-and-accuracy-of-datetime.aspx

话虽如此,如果您将值转换为较小的类型,默认情况下您可以在任何情况下丢失数据。

考虑这个输出:

int.MaxValue:       2147483647
DateTime.Now.Ticks: 634075598514933010

如何将这个转换成int是一个现实的选择?

答案 1 :(得分:11)

你需要所有最重要的部分吗? (例如哪一年)

你需要所有最不重要的位吗? (例如,亚纳秒精度)

您需要测量多长时间间隔?

如果只需要毫秒精度,为什么不丢失最低有效位

int timeStamp = (int)(DateTime.Now.Ticks >> 10) // lose smallest 10 bits

修改

OP希望存储最近使用过的项目的时间:如果这是单个用户的用户选择,您可能不希望任何短于一秒的内容!因为每秒有10 ^ 7个滴答,所以长值中有log(10 ^ 7)/ log(2)= 23个超额位!

那么你需要多少空间?那么,你的价值观应该指明年,月,日,时,分和秒;一年大约有3200万秒=大约24位。如果您想存储过去10年的价值,请添加3位。因此很容易融入int32。 我建议

int timeStamp = (int)(DateTime.Now.Ticks >>23) // retain bits 23 to 55

答案 2 :(得分:2)

如果毫秒级的分辨率足够好,您可以在DataTime字段中存储某些基数int的偏移量,然后在需要时重建完整的DateTime。存储在32位整数中的毫秒数将允许您的应用程序在包装之前运行49天。这是一个你可以使用的简单助手类:

public class TimeOffsetManager
{
    public TimeOffsetManager()
    {
        InitialDateTime = DateTime.Now;
    }

    public DateTime InitialDateTime { get; private set; }

    public int GetOffset()
    {
        TimeSpan elapsed = DateTime.Now - InitialDateTime;
        return (int)Math.Round(elapsed.TotalMilliseconds);
    }

    public DateTime OffsetToDateTime(int offset)
    {
        return InitialDateTime + TimeSpan.FromMilliseconds(offset);
    }
}

可以像:

一样使用
public static void Method()
{
    var offsetManager = new TimeOffsetManager();

    int offset = offsetManager.GetOffset();

    // ...

    DateTime realTime = offsetManager.OffsetToDateTime(offset);
}

答案 3 :(得分:2)

更多关于踢的事情......如果你已经设置了使用整数存储你的DateTime并保持精度,你可以定义你自己的包含两个整数的结构,每个整数包含4个字节,以及一个分享这些整数的日期时间字节。

public class Program
{
    public static void Main(string[] args)
    {
        DateTime now = DateTime.Now;
        var myDate = new Int32BackedDate(now.Ticks);

        Console.WriteLine(now);
        Console.WriteLine(myDate.Date);
    }
}

[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct Int32BackedDate
{
    [FieldOffset(4)]
    private readonly int _high;

    [FieldOffset(0)]
    private readonly int _low;

    [FieldOffset(0)]
    private readonly DateTime _date;

    public DateTime Date { get { return _date; } }

    public Int32BackedDate(long ticks)
    {
        _date = default(DateTime);
        byte[] bytes = BitConverter.GetBytes(ticks);
        _low = BitConverter.ToInt32(bytes, 0);
        _high = BitConverter.ToInt32(bytes, 4);
    }
}

答案 4 :(得分:1)

参考上面的评论。准确的约束是什么?如果约束是你不能将数据存储在64位变量中,那么如何做一些事情。

uint tsLow = (uint)DateTime.Now.Ticks;
uint tsHigh = (uint)(DateTime.Now.Ticks >> 32);

现在您可以将tsLow和tsHigh存储到外部数据中。您还可以实现可以使用两个单独的32位数来计算值的特殊函数,以执行您自己的64位数学运算。

这实际上取决于你的实际约束。了解这些将有助于提出更好的解决方案。