使用毫秒精度获取当前时间DateTime.Now

290

我如何准确构建毫秒级别的实际时间戳?

我需要像“16.4.2013 9:48:00:123”这样的时间戳。这可能吗? 我有一个应用程序,每秒采样10个值,并且需要在图表中显示它们。


相关内容请参考:http://msdn.microsoft.com/zh-cn/library/bb882581.aspx - Soner Gönül
请注意,一些答案使用 hh 表示小时(标准时间)。在时间戳(以及许多其他情况)中,这可能应该与 tt(上午/下午)配对,或者替换为 HH(军事时间)。 - wentz
12个回答

379
如何以毫秒精度构建实际时间的时间戳? 我猜你指的是毫秒精确度。DateTime具有很高的精度,但在准确性方面相对较差。一般来说,你做不到。通常系统时钟(这就是DateTime.Now获取数据的地方)的分辨率约为10-15毫秒。有关详细信息,请参见Eric Lippert的有关精度和准确性的博客文章
如果您需要比此更准确的计时,则可能需要考虑使用NTP客户端。
然而,您是否真的需要毫秒级的准确性尚不清楚。如果您不在乎确切时间,只是想以“相当不错”的准确性正确显示样本,那么系统时钟应该没有问题。我建议您使用DateTime.UtcNow而不是DateTime.Now,以避免夏令时转换等时区问题。
如果您的问题实际上只是围绕将DateTime转换为具有毫秒精度的字符串,则建议使用:
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
                                            CultureInfo.InvariantCulture);

(请注意,与您的示例不同,此选项可排序,并且不太可能引起围绕其是否意味着“月/日/年”或“日/月/年”的混淆。)


6
只凭“不工作”这样的信息,我无法提供更多帮助。 - Jon Skeet
是的,我可以提供更多信息: "{0:yyyyMMdd HH:mm:ss.fff}",DateTime.UtcNow -> 20180502 11:07:20.000 Win32.GetSystemTime(ref stime) -> 2018,2,5,11,7,20,0 (年 月 日 时 分 秒 毫秒) 我可以创建一个带有毫秒的日期时间实例: var dt = new DateTime(2018, 5, 2, 19, 34, 55, 200); "{0:yyyyMMdd HH:mm:ss.fff}", dt -> 20180502 19:34:55.200 .Net Compact Framework,Windows Embedded Compact 7,在 ARM Cortex-A8 上。 - antonio
@antonio:所以听起来你在使用的硬件上使用的.NET版本根本没有提供亚秒级别的精度,或者你碰巧在秒边界上调用了它。(如果你不断地调用DateTime.UtcNow,它每秒只会增加一次吗?你还没有展示出来。) - Jon Skeet
当我从DateTime.Now检索Ticks时,值会被截断:Ticks 636534596580000000 从Ticks转换为DateTime是20180205 20:34:18.000。 我认为这是硬件/软件的限制。 我改用了Stopwatch类。 谢谢Jon。 - antonio
1
@kuldeep:我担心如果你已经提出了足够糟糕的问题而被封禁,我不会通过评论进入应该是另一个问题的领域来绕过这个问题。我建议你编辑旧问题使其更好,试图解除禁令。 - Jon Skeet
显示剩余4条评论

142
这应该能够正常工作:
DateTime.Now.ToString("hh.mm.ss.ffffff");

如果你只需要知道时间差异而不需要将其显示出来,那么就不要将其转换为字符串。将其保留为 DateTime.Now();

使用 TimeSpan 来了解时间间隔之间的差异:

示例

DateTime start;
TimeSpan time;

start = DateTime.Now;

//Do something here

time = DateTime.Now - start;
label1.Text = String.Format("{0}.{1}", time.Seconds, time.Milliseconds.ToString().PadLeft(3, '0'));

我需要对它进行计算,所以不能将其转换为字符串。 - LuckyHK
请注意,对于“子秒”,最高精度似乎为7,例如“hh.mm.ss.fffffff”。 - Nae

29

我正在寻找类似的解决方案,基于这个帖子中的建议,我使用以下代码: DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff") ,并且它可以完美地工作。注意:其中的.fff是您想要捕获的精度数字。


1
如果日期在下午(4点),将显示为上午。 修复:使用HH(军事时间)或添加tt(PM或AM)。 如此示例所示:https://repl.it/KGr3/1 - Jaider

22

使用毫秒的 DateTime 结构并按以下格式进行格式化:

string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", 
CultureInfo.InvariantCulture);
timestamp = timestamp.Replace("-", ".");

17

Pyromancer的回答 对我来说看起来很不错,但是也许你想要:

DateTime.Now.Millisecond

但如果你要比较日期,TimeSpan 是更好的选择。


19
注意:如果您要将两个DateTime作为TimeSpan进行比较,您需要使用TotalMilliseconds。 Milliseconds属性只保留当前的毫秒计数器,该计数器永远不会大于1000,而TotalMilliseconds属性则保留自历元以来经过的总毫秒数。 - Contango

6
如果您仍希望得到一个日期而不是其他答案里的字符串,只需添加这个扩展方法即可。
public static DateTime ToMillisecondPrecision(this DateTime d) {
    return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute,
                        d.Second, d.Millisecond, d.Kind);
}

3
据我理解,你可以选择以下方案:
DateTime dateTime = DateTime.Now;
DateTime dateTimeInMilliseconds = dateTime.AddTicks(-1 * dateTime.Ticks % 10000); 

这将移除小于1毫秒的时刻。

是的,但是DateTime.Now的实际分辨率可能不超过16毫秒。 - Peter Mortensen

3

另一个选项是根据源DateTime值构建新的DateTime实例:

// current date and time
var now = DateTime.Now;

// modified date and time with millisecond accuracy
var msec = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond, now.Kind);

不需要进行任何的字符串转换,代码也非常易于理解和阅读。


2
“DateTime.UtcNow”和“DateTime.Now”的问题在于,根据计算机和操作系统的不同,它们可能只精确到10至15毫秒之间。然而,在Windows计算机上,可以使用低级函数GetSystemTimePreciseAsFileTime来获得微秒级精度,请参见下面的函数“GetTimeStamp()”。
    [System.Security.SuppressUnmanagedCodeSecurity, System.Runtime.InteropServices.DllImport("kernel32.dll")]
    static extern void GetSystemTimePreciseAsFileTime(out FileTime pFileTime);

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct FileTime  {
        public const long FILETIME_TO_DATETIMETICKS = 504911232000000000;   // 146097 = days in 400 year Gregorian calendar cycle. 504911232000000000 = 4 * 146097 * 86400 * 1E7
        public uint TimeLow;    // least significant digits
        public uint TimeHigh;   // most sifnificant digits
        public long TimeStamp_FileTimeTicks { get { return TimeHigh * 4294967296 + TimeLow; } }     // ticks since 1-Jan-1601 (1 tick = 100 nanosecs). 4294967296 = 2^32
        public DateTime dateTime { get { return new DateTime(TimeStamp_FileTimeTicks + FILETIME_TO_DATETIMETICKS); } }
    }

    public static DateTime GetTimeStamp() { 
        FileTime ft; GetSystemTimePreciseAsFileTime(out ft);
        return ft.dateTime;
    }

非常感谢。我已经搜索了很长时间了。它是否会导致性能问题,以及在生产环境中使用是否安全? - Muhammet Göktürk Ayan

0

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