【问题标题】:Datetime.Now evaluation in function callDatetime.Now 函数调用中的评估
【发布时间】:2016-10-23 11:05:48
【问题描述】:

我目前正在编写一段代码,我需要根据一年中的当前周命名一个文件夹(根据 ISO8601 标准)。

文件夹将被命名为:“y[year]w[week-of-year]”。例如,本周的文件夹名称可能是“y2016w42”。

我目前正在做以下事情:

DateTime n = DateTime.Now;
string folderName = "y" + n.Year + "w" + DataHelper.WeekOfYearISO8601(n);

我首先将当前时间分配给变量 n,然后使用它来生成文件夹名称。

现在我实际上宁愿做以下事情:

string folderName = "y" + DateTime.Now.Year + "w" + DataHelper.WeekOfYearISO8601(DateTime.Now);

DateTime.Now 是否计算一次或两次实际时间?编译器是从第一次评估中重新使用它,还是在这种情况下我实际上得到了两个不同的时间戳?

我确信这段代码在 99.9999% 的时间里都能正常工作,但是如果这段代码在新年之夜午夜运行会发生什么? (让我们忽略这一事实,即根据 ISO8601 标准,一年中的一周在 NYE 上不一定会发生变化,并假装它们今年是一致的)。

如果 DateTime.Now 被评估两次,我可以想象其中一个 DateTimes 仍在 2016 年第 52 周,另一个在 2017 年第 1 周。这可能会带来麻烦,因为文件夹可能会被命名为“ 2017_52" 或 "2016_1",两者都是错误的 - 正确的是 "2017_1" 或 "2016_52"。

我确定我提供的第一个 sn-p 代码没问题,但第二个 sn-p 是否也适用于所有场景?

【问题讨论】:

  • 为什么更喜欢第二个版本? (恕我直言,第一个版本更具可读性,因此更容易理解)
  • string folderName = "y%sw%s" % (n.Year, DataHelper.WeekOfYearISO8601(n)) 将是我的首选方式:字符串连接很慢,因为字符串在 Python 中是不可变的。填充格式字符串更快。
  • @dexter:我认为“DateTime.Now”和“n”一样难以理解,因此额外的变量似乎是不必要的,特别是因为我发现自己经常使用 DateTime。
  • @TemporalWolf:问题是 C#,但是你是对的,String.Format 会更好。

标签: c# datetime


【解决方案1】:

DateTime.Now 是否计算一次或两次实际时间?

因为你调用了两次DateTime.Now,所以它被计算了两次。

我确信这段代码在 99.9999% 的情况下都能正常工作,但如果这样会发生什么 代码要在新年晚上午夜运行?

没错。由于此表达式计算了两次,它们可能生成不同的结果(假设两个属性调用之间的时钟确实Tick)。

使用第一个,卢克。

【讨论】:

    【解决方案2】:

    据我所知,DateTime.Now 每次被调用时都会被评估。可能有一些我不知道的优化,但为了安全起见,您应该将其视为事实。

    在这 0.0001% 的时间里(如果有的话,可能要少得多)保持安全,您应该做的是将 DateTime.Now 保留在一个变量中,我真的认为您的首选选项没有很大优势。

    如果可能,您可以确保它永远不会在午夜运行,这也可以解决您的问题..

    【讨论】:

      【解决方案3】:

      DateTime.Now 每次被调用时都会重新评估,分辨率约为 10 毫秒(这里有一个关于它的准确度的很好的讨论:How does DateTime.Now.Ticks exactly work?

      你可以很容易地看到这个(现场版本:http://rextester.com/XJVEJ16515):

      Console.WriteLine(DateTime.Now.Ticks);
      
      var currVal = DateTime.Now.Ticks;
      for (int i = 0; i < 10000; i++) {
          if (currVal != DateTime.Now.Ticks) {
              Console.WriteLine(currVal);
              currVal = DateTime.Now.Ticks;
          }
      }
      

      输出:

      > 636128255483021039 
      > 636128255483177570
      > 636128255483333827
      > 636128255483489977 
      > 636128255483646493 
      > 636128255483802799
      > 636128255483959218 
      > 636128255484115758 
      > 636128255484271805
      > 636128255484428165
      

      在这种情况下,它实际上并不是每毫秒拆分一个新值

      缓存该值并像在原始代码中一样使用它;它更安全,但也更容易阅读!

      【讨论】:

      • 是的,即使写到控制台应该也需要一点时间。
      【解决方案4】:

      将当前的 DateTime 保存在变量中是最好的选择。如果你调用 DateTime.Now 两次,你会得到不同的时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-02
        • 1970-01-01
        • 2019-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多