【问题标题】:How does DateTime.Now works?DateTime.Now 是如何工作的?
【发布时间】:2017-07-20 08:58:23
【问题描述】:

我发现了一些看起来像这样的代码:

var obj = new SomeClass();
obj.FirstProperty = Magic.GetFirstProperty();
//...
obj.CreateDate = DateTime.Now;
obj.ModificationDate = obj.CreateDate;

有很多属性,所以我决定重构代码并使用对象初始化器。

var obj = new SomeClass
{
    FirstProperty = Magic.GetFirstProperty();
    //...
    CreateDate = DateTime.UtcNow,
    ModificationDate = DateTime.UtcNow
};

在对象初始化块中将属性从一个重写到另一个是不可能的(据我所知),并且在块外执行它看起来很糟糕(在我看来)。

我决定进行一次测试,经过 10 000 000 次迭代,我得到了 600 到 1200 对不同的配对。这是代码:

class Program
{
    static void Main(string[] args)
    {
        int j = 0;
        for (int i = 0; i < 10000000; i++)
        {
            var obj = new SomeClass
            {
                First = DateTime.UtcNow,
                Second = DateTime.UtcNow
            };

            if (obj.First != obj.Second)
                Console.WriteLine(j++ + "  :  " + GetDateInfo(obj.First) + "  " + GetDateInfo(obj.Second));
        }
        Console.WriteLine("End of work");
        Console.ReadKey();
    }

    static string GetDateInfo(DateTime dateTime) =>
        $"{dateTime.Hour} : {dateTime.Minute} : {dateTime.Second} : {dateTime.Millisecond} -  {dateTime.Ticks}";
}

internal class SomeClass
{
    public DateTime First { get; set; }
    public DateTime Second { get; set; }
}

这里我们有一些结果:

如您所见,某些记录(如 highlithed 记录)仅在处理器滴答数上有所不同。

同时,javascript 总是返回相同的值,除了 Google Chrome 中的内存泄漏。这是代码:

var d,d2,n,n2;
for(var i=0; i<1000000; i++) {
    d = new Date();
    n = d.getTime();
    d2 = new Date();
    n2 = d.getTime();

    if(n===n2) 
        console.log("equal"); 
    else 
        console.log("not equal");  
}

您是否知道如何在 .NET 中以适当的方式解决该问题以及 DateTime.Now 的实际工作原理?我很好奇幕后发生了什么。 我期望一次迭代/对象初始化中的两个值是相等的。

【问题讨论】:

  • 你有一个循环需要一些时间来执行。为什么你期望DateTime.Now/UtcNow 总是在同一时间返回?如果您运行一周的循环,您仍然希望从上周获得DateTime?至于“日期时间是如何工作的”,请始终阅读documentation
  • 您的代码中有严重的拼写错误。它应该是“n2 = d2.getTime();”
  • @TimSchmelter 请再次阅读 OP 的代码。他不希望两个不同的对象DateTime 值相同,他希望同一个对象的两个不同属性得到相同的 Date 值
  • OP,.getTime() 返回 13 位数字,而 .Ticks 返回 18 位。那是整整 5 位的精度。您突出显示的差异在最后 4 位。想想吧。
  • @er-han 他的 JavaScript 测试似乎与此相矛盾。

标签: javascript c# datetime


【解决方案1】:

您知道如何在 .NET 中以适当的方式解决该问题...

解决方法很简单,只需调用一次 DateTime.UtcNow...

var dtNow = DateTime.UtcNow;
var obj = new SomeClass
{
    FirstProperty = Magic.GetFirstProperty();
    //...
    CreateDate = dtNow,
    ModificationDate = dtNow
};

在循环的情况下,如果您希望所有值完全相同,那么您应该在循环开始之前分配dtNow。即只分配一次。


...DateTime.Now 实际上是如何工作的?

简而言之,它会在您调用DateTime.UtcNow 时获取当前值。

总之,你应该看看documentation,如果你真的有兴趣做进一步的研究。

【讨论】:

  • 是的,这就是解决方案。但我真的很想知道为什么 OP 期望他在循环运行一段时间后得到旧的 DateTime 值
  • @TimSchmelter:我同意,这真是一个奇迹......为什么随着时间的推移会导致不同时间的循环似乎很明显
  • @TimSchmelter 我猜 OP 期望 UtcNow 调用只执行一次,没有意识到对象初始化程序代码只是围绕几个顺序调用的语法糖。所以问题不在于 DateTime.UtcNow 是如何工作的,而在于 C# 语法。
  • @DavidG:类似的东西,但我仍然不明白为什么有人期望循环内的语句只能执行一次,就好像它是在外面完成的一样。也许Now是一个属性这一事实让他感到困惑,但Now这个名字很有意义;)
  • 我期待一次迭代/对象初始化中的两个值将相等。 DateTime.Now 调用两次,一一会得到相同的结果。
【解决方案2】:

Js Date.now() 方法具有毫秒分辨率。如果您需要更高的分辨率,请使用Performance.now()Date.now()

正式地,C# DateTime 使用 100 ns 滴答。但在实际情况下很难达到这个分辨率。 High-Precision Code Timing in .NET

这意味着如果在对DateTime.Now 的两次调用之间传递了不止一个刻度,则创建的DateTime 对象将具有不同的值。

对于您的用例,获得完全相同的时间戳的最简单方法是只调用一次 DateTime.Now 并分配此值。

var now = DateTime.UtcNow;
var obj = new SomeClass
   {
       FirstProperty = Magic.GetFirstProperty();
       (...)
       CreateDate = now,
       ModificationDate = now 
   };

【讨论】:

    【解决方案3】:

    DateTime.Now(和 UtcNow)使用内部窗口函数返回当前时间。每次调用它都会返回当前时间,所以调用之间当然会有微小的差异。

    解决方案:

    • 将当前时间分配给一个变量并使用该变量来初始化 obj 属性。

    • 如果这是您自己的类,请创建一个适当的构造函数来自动初始化属性。

    这与 JavaScript 不同,后者在创建 Date 对象后设置当前时间。调用它的任何函数都会返回对象的创建时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-01
      • 2012-08-09
      • 2019-12-19
      • 1970-01-01
      • 1970-01-01
      • 2017-07-24
      • 2016-11-13
      • 2017-10-11
      相关资源
      最近更新 更多