如何在 C# 中使用 DateTime.Now.Ticks 保持精度
Posted
技术标签:
【中文标题】如何在 C# 中使用 DateTime.Now.Ticks 保持精度【英文标题】:How to maintain precision using DateTime.Now.Ticks in C# 【发布时间】:2011-02-11 07:29:42 【问题描述】:我知道当我在 C# 中使用 DateTime.Now.Ticks 时,它会返回一个 long 值,但我需要将它存储在一个 int 变量中,我很困惑我是否可以保持这种精度。到目前为止,我只有一个演员表
int timeStampValue = (int)DateTime.Now.Ticks;
这是一个项目限制,所以我知道有大量的精度损失。我想我只是想不出另一种方法来执行存储在 int 中的时间戳事情,然后我可以将其与其他时间戳进行比较。
如果可能的话,任何关于如何保持精度的建议或意见将不胜感激。
每个人的回答都是说明性的。实际上,我最终只是设置了一个涉及计数器的过程,当使用一个项目时,它的计数器设置为“0”,所有其他计数器都增加 1。然后,最高的计数器是下一个要使用的项目。
【问题讨论】:
为什么要存储在int中? 这是一个项目约束,这是我能想到的唯一方法,而且我过去不需要做时间戳的东西。 是不是根本不允许使用long,还是只用于存储到外部数据?例如,如果您可以使用 long 来获取数据,然后存储两个 int? 不允许使用long,我只能使用int 说你根本不能使用整数并没有真正给出限制。这是由于嵌入式系统吗?您在调用 '(int)DateTime.Now.Ticks;' 的那一刻使用 longs看看我下面的解决方案。您可以使用两个 uint 来表示整个时间戳 long 值,并为您可能需要做的任何数学创建自己的方法。这将允许您仅使用整数来获得完整分辨率。 【参考方案1】:您需要所有最重要的位吗? (例如哪一年)
您需要所有最低有效位吗? (例如亚纳秒精度)
您需要测量多长时间的间隔?
如果您只需要毫秒精度,为什么不丢失最低有效位
int timeStamp = (int)(DateTime.Now.Ticks >> 10) // lose smallest 10 bits
编辑
OP 想要存储最近使用的项目的时间:如果这是单个用户的用户选择,您可能不想要任何短于一秒的内容!因为每秒有 10^7 个滴答声,所以 long 值中有 log(10^7)/log(2)=23 多余的位!
那么您需要多少空间?好吧,您的值应该指定年、月、日、小时、分钟和秒;一年大约有 3200 万秒 = 大约 24 位。如果要存储最近 10 年的价值,请添加 3 位。所以很容易适应 int32。 我建议
int timeStamp = (int)(DateTime.Now.Ticks >>23) // retain bits 23 to 55
【讨论】:
我需要能够跟踪数组中最近最少使用的项目。【参考方案2】: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 是一个现实的选择?
【讨论】:
是的,虽然我真的别无选择,但这并不是一个现实的选择,这只是我想到的第一个想法【参考方案3】:如果一毫秒的分辨率足够好,您可以将一些基本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);
【讨论】:
【参考方案4】:比什么都重要...如果您死心塌地使用整数来存储您的 DateTime 并保持精度,您可以定义自己的结构,其中包含两个整数,每个包含 4 个字节,以及一个共享这些整数的 DateTime字节。
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);
【讨论】:
【参考方案5】:参考我上面的评论。究竟是什么约束?如果限制是您不能将数据存储在 64 位变量中,那么如何按照以下方式进行操作。
uint tsLow = (uint)DateTime.Now.Ticks;
uint tsHigh = (uint)(DateTime.Now.Ticks >> 32);
现在您可以将 tsLow 和 tsHigh 都存储到您的外部数据中。您还可以实现特殊函数,使用两个单独的 32 位数字计算值来进行您自己的 64 位数学运算。
这实际上取决于您的实际限制。了解这些将有助于提出更好的解决方案。
【讨论】:
以上是关于如何在 C# 中使用 DateTime.Now.Ticks 保持精度的主要内容,如果未能解决你的问题,请参考以下文章