DateTime.Now vs. DateTime.UtcNow

后端 未结 13 1488
暗喜
暗喜 2020-11-28 17:43

I\'ve been wondering what exactly are the principles of how the two properties work. I know the second one is universal and basically doesn\'t deal with time zones, but can

13条回答
  •  情歌与酒
    2020-11-28 18:37

    This is a good question. I'm reviving it to give a little more detail on how .Net behaves with different Kind values. As @Jan Zich points out, It's actually a critically important property and is set differently depending on whether you use Now or UtcNow.

    Internally the date is stored as Ticks which (contrary to @Carl Camera's answer) is different depending on if you use Now or UtcNow.

    DateTime.UtcNow behaves like other languages. It sets Ticks to a GMT based value. It also sets Kind to Utc.

    DateTime.Now alters the Ticks value to what it would be if it was your time of day in the GMT time zone. It also sets Kind to Local.

    If you're 6 hours behind (GMT-6), you'll get the GMT time from 6 hours ago. .Net actually ignores Kind and treats this time as if it was 6 hours ago, even though it's supposed to be "now". This breaks even more if you create a DateTime instance then change your time zone and try to use it.

    DateTime instances with different 'Kind' values are NOT compatible.

    Let's look at some code...

        DateTime utc = DateTime.UtcNow;
        DateTime now = DateTime.Now;
        Debug.Log (utc + " " + utc.Kind);  // 05/20/2015 17:19:27 Utc
        Debug.Log (now + " " + now.Kind);  // 05/20/2015 10:19:27 Local
    
        Debug.Log (utc.Ticks);  // 635677391678617830
        Debug.Log (now.Ticks);  // 635677139678617840
    
        now = now.AddHours(1);
        TimeSpan diff = utc - now;
        Debug.Log (diff);  // 05:59:59.9999990
    
        Debug.Log (utc <  now);  // false
        Debug.Log (utc == now);  // false
        Debug.Log (utc >  now);  // true
    
        Debug.Log (utc.ToUniversalTime() <  now.ToUniversalTime());  // true
        Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime());  // false
        Debug.Log (utc.ToUniversalTime() >  now.ToUniversalTime());  // false
        Debug.Log (utc.ToUniversalTime() -  now.ToUniversalTime());  // -01:00:00.0000010
    

    As you can see here, comparisons and math functions don't automatically convert to compatible times. The Timespan should have been almost one hour, but instead was almost 6. "utc < now" should have been true (I even added an hour to be sure), but was still false.

    You can also see the 'work around' which is to simply convert to universal time anywhere that Kind is not the same.

    My direct answer to the question agrees with the accepted answer's recommendation about when to use each one. You should always try to work with DateTime objects that have Kind=Utc, except during i/o (displaying and parsing). This means you should almost always be using DateTime.UtcNow, except for the cases where you're creating the object just to display it, and discard it right away.

提交回复
热议问题