使用C#获取毫秒级时间

173

我正在制作一个程序,需要获取毫秒级别的时间。所谓的时间是指一个数字,它从未等于自身,并且始终比一秒前大1000个数字。我尝试将DateTime.Now转换为TimeSpan,并从中获取TotalMilliseconds... 但我听说这种方法并不完全准确。

有更简单的方法吗?


你是否期望任何两个调用总是导致递增的值?一般来说,比计时器分辨率允许的最小间隔更接近的调用将产生相同的值。您需要添加自己的解决方法,以形式化假精度序列化程序。 - Steven Sudit
21
永远不等于它本身的数字。听起来有点复杂。 ;) - Mizipzor
2
实际上,NaN符合该要求。尽管它是“不是数字”,但它是一种数字类型,并且它不等于自身。 - Yay295
10个回答

430
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

这实际上是Unix转换方法在 DateTimeOffset 类(.NET Framework 4.6+,.NET Standard 1.3+)中的实现:

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();

78
标题是“以毫秒为单位获取时间”。这个回答很有帮助。 - Aerospace
40
非常感谢你提供的答案,对于那些正在寻找如此问题的答案的人来说,这非常有帮助。 - user430788
1
如果你想要小数位数(即使 DateTime.Now 并不经常更新),那么可以使用以下代码: decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond; - Jeppe Stig Nielsen
1
这比所选答案对于搜索结果以及从原始问题中收集的信息都更有用。 - bwoogie
1
这个答案救了我的命。我有类似的代码,但是不起作用。一直想不明白为什么。然后我看到毫秒前面的 long 数据类型。使用 int 肯定会溢出。 - FisNaN
显示剩余3条评论

83

8
秒表是诊断工具的一部分。它应该在真实代码中使用吗? - Andrey
5
@Andrey - https://dev59.com/tXE85IYBdhLWcg3wYSZk#2805409 - John Rasch
12
多贵啊?也许我们应该用秒表计时 :) - jb.
3
@Steven,这取决于操作系统和底层硬件。如果可用,将使用高分辨率计时器,在我所知道的所有当前桌面和服务器基于x86的Windows版本中都是如此。有关更多详细信息,请检查频率和IsHighResolution属性。在操作系统级别上,QueryPerformanceCounter和QueryPerformanceFrequency是支持此功能的低级API。 - Chris Taylor
这不应该是答案。问题是如何获取当前时间的毫秒数,而不是记录时间的流逝。 - KWallace
显示剩余4条评论

19

DateTime.Ticks属性获取表示日期和时间的滴答数。

10000个Ticks是1毫秒 (每秒钟有10,000,000个ticks)。


5
但是Ticks的分辨率很低,不到1/10000秒,可能只有1/62秒。 - codymanix
2
@codymanix - 来自 MSDN:一个滴答代表一百纳秒或者说是一千万分之一秒。一毫秒包含 10,000 个滴答。 - Itay Karo
7
当然可以,但操作系统没有这么准确的分辨率。 - codymanix
6
@codymanix 是正确的。类比地,埃(Angstrom)是一个长度单位;一米等于十亿埃。你可以编写一个函数,以埃为单位报告您的身高,但如果您只有一根精确到厘米的米棒,那么该函数表示亚纳米级精度这一事实就完全不相关了。较不重要的数字将是无用的垃圾数据。 - Eric Lippert
@Itay:这就像用毫秒告诉别人你的年龄一样 - 在你说出来的时候,它已经过时了。 - D'Arcy Rittich
4
如果你能准确知道自己的年龄到毫秒,你可以说:“当我再眨眼时,我的年龄将是x毫秒。” 更深层次的问题不在于交流,而在于测量:你的出生时间甚至可能无法准确到秒。 - Steven Sudit

13

我使用以下类。我曾经在互联网上找到它,被认为是最好的NOW()

/// <summary>Class to get current timestamp with enough precision</summary>
static class CurrentMillis
{
    private static readonly DateTime Jan1St1970 = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    /// <summary>Get extra long current timestamp</summary>
    public static long Millis { get { return (long)((DateTime.UtcNow - Jan1St1970).TotalMilliseconds); } }
}

来源不明。


5
这个常用代码片段的全部目的,就是生成一个与Unix时间戳标准兼容的时间戳。对于此目的,它是至关重要的。但如果只想计时,使用它会显得不必要地耗费资源。 - ToolmakerSteve
当需要从C#传递毫秒给Java时,这将非常有用。 - Nick

8
您可以尝试使用QueryPerformanceCounter本地方法。有关更多信息,请参见http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html。这是Stopwatch类使用的方法。

有关更多信息,请参见如何在.NET/C#中以tick精度获取时间戳?

Stopwatch.GetTimestamp()提供了访问此方法的途径:

public static long GetTimestamp() {
     if(IsHighResolution) {
         long timestamp = 0;
         SafeNativeMethods.QueryPerformanceCounter(out timestamp);
         return timestamp;
     }
     else {
         return DateTime.UtcNow.Ticks;
     }
 }

1
据我所知,如果可用,StopWatch 内部使用 QueryPerformanceCounter。 - codymanix
是的,Stopwatch.GetTimestamp() 的内部实现确实提供了对该方法的访问。 - Pieter van Ginkel

7
我使用了DateTime.Now.TimeOfDay.TotalMilliseconds(用于当前日期),希望这也能帮到你。

1
该方法无法返回增加的值(如原帖所需求),因为TimeOfDay在每天午夜时会重置为零。此外,当仅使用DateTime.Now并获取其总毫秒数时,它也可能存在与原贴中提到的相同潜在问题。 - Jim O'Neil
3
我同意Jim O'Neil的观点,这就是为什么我在我的帖子中提到了“(for current day)”... 顺便说一句,我的解决方案适用于我的问题,因为我的问题不是特定日期的,我只需要获得毫秒部分用作计数器,所以我在这里发布了它。我是新手,如果我发错地方了,对不起 :) - Sarvan

2
使用 Stopwatch 类,我们可以从 System.Diagnostics 实现它。
Stopwatch stopwatch  = new Stopwatch();
stopwatch.Start();
stopwatch.Stop();
Debug.WriteLine(stopwatch.ElapsedMilliseconds);

2

使用System.DateTime.Now.ToUniversalTime()。这将以已知的基于参考的毫秒格式提供您的日期和时间,完全消除了日期更改等问题。


很好知道,但与所问问题无关,该问题涉及时间测量(时间经过的测量),而不是准确传达时间。 - ToolmakerSteve

1

1
据我理解,Environment.TickCount 符合您的要求。它返回自启动以来的毫秒数,因此它始终增加并可用于计算已过去的毫秒数。如果您还想要绝对时间,可以获取当前时间和当前的 Environment.TickCount,并基于此计算新的绝对时间和新的 Environment.TickCount。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接