255

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 someone explain in detail how they work and which one should be used in what scenario?

Jedi Master Spooky
  • 5,143
  • 11
  • 49
  • 85
Slavo
  • 14,445
  • 10
  • 42
  • 59

13 Answers13

386

DateTime.UtcNow tells you the date and time as it would be in Coordinated Universal Time, which is also called the Greenwich Mean Time time zone - basically like it would be if you were in London England, but not during the summer. DateTime.Now gives the date and time as it would appear to someone in your current locale.

I'd recommend using DateTime.Now whenever you're displaying a date to a human being - that way they're comfortable with the value they see - it's something that they can easily compare to what they see on their watch or clock. Use DateTime.UtcNow when you want to store dates or use them for later calculations that way (in a client-server model) your calculations don't become confused by clients in different time zones from your server or from each other.

Leniel Maccaferri
  • 94,281
  • 40
  • 348
  • 451
Blair Conrad
  • 202,794
  • 24
  • 127
  • 110
  • 91
    an excellent point -- when *storing* dates in a database or file, definitely store them in UTC! – Jeff Atwood Sep 15 '08 at 11:04
  • 16
    You have to note that when you want to store dates in UTC in the database, you have to make sure that the database doesn't add its own timezone to dates that don't give explicit timezones. Note that DateTime will always use the current timezone when asked for one. – Omer van Kloeten Sep 15 '08 at 11:25
  • @OmervanKloeten gives a very good point. I'm wondering if there is an elegant 'all round' solution for this, to store and recieve dates correctly every time, even if your IIS and SQL server are in different timezones. – TheGeekZn May 23 '14 at 11:34
  • Is it possible to add 1 year to DateTime.UtcNow? For example, and expiration date for a user account. – JoshYates1980 May 22 '15 at 16:24
  • 1
    @JoshYates1980 Yes you just do DateTime.UtcNow.AddYears(1) – CathalMF Nov 30 '15 at 14:21
  • 3
    Use [NodaTime](http://nodatime.org/) - it'll force you think about time in a more useful way and avoided such problems – aateeque Apr 13 '16 at 22:43
  • 1
    I am sure when you say "I'd recommend using DateTime.Now", it was 2008 and cloud didn't exist. Do you not think that UTC.Now is the right option these days when everything is deployed on geo-distributed cloud with international audience ? – Sagar Khatri Oct 18 '19 at 10:39
  • wont DateTime.Now give you the server date and time and not the client date and time? looking at capturing the client date and time. How do I do it without complications? – Oracular Man Apr 17 '20 at 01:47
  • I am getting error ``NoMethodError (undefined method `UtcNow' for DateTime:Class)`` – Chetan Kumar Dec 21 '20 at 15:11
  • As an example, I am living in Turkey and my clock shows 21:39 at night here. So DateTime.Now gives me 21:39:18. DateTime.UtcNow gives me 18:39:18 since London is having an evening right now. – Onat Korucu Jan 02 '21 at 18:42
93

It's really quite simple, so I think it depends what your audience is and where they live.

If you don't use Utc, you must know the timezone of the person you're displaying dates and times to -- otherwise you will tell them something happened at 3 PM in system or server time, when it really happened at 5 PM where they happen to live.

We use DateTime.UtcNow because we have a global web audience, and because I'd prefer not to nag every user to fill out a form indicating what timezone they live in.

We also display relative times (2 hours ago, 1 day ago, etc) until the post ages enough that the time is "the same" no matter where on Earth you live.

Jeff Atwood
  • 60,897
  • 45
  • 146
  • 152
  • I want also second that storing DateTime.UtcNow is also only needed when calculation with 2 dates are done to get the correct hours. When I just have to display a RegisterAt Date then Datetime.Now is enough. – Elisabeth Jul 14 '16 at 20:50
43

Also note the performance difference; DateTime.UtcNow is somewhere around 30 times faster then DateTime.Now, because internally DateTime.Now is doing a lot of timezone adjustments (you can easily verify this with Reflector).

So do NOT use DateTime.Now for relative time measurements.

Yousha Aleayoub
  • 3,221
  • 2
  • 42
  • 58
Magnus Krisell
  • 480
  • 4
  • 7
  • It has taken me a painful journey just know UtcNow has better performance and that simply saving your dates in mysql and assuming that is utc and comparing date dependent displays with UtcNow simplifies this global timezone issues – Diin May 14 '19 at 16:48
  • On my computer is only `3` times faster. I created a loop with one million iterations. Using datetime.now took 200ms. Using datetime.utcnow took 60ms. – Tono Nam Nov 10 '20 at 15:39
32

One main concept to understand in .NET is that now is now all over the earth no matter what time zone you are in. So if you load a variable with DateTime.Now or DateTime.UtcNow -- the assignment is identical.* Your DateTime object knows what timezone you are in and takes that into account regardless of the assignment.

The usefulness of DateTime.UtcNow comes in handy when calculating dates across Daylight Savings Time boundaries. That is, in places that participate in daylight savings time, sometimes there are 25 hours from noon to noon the following day, and sometimes there are 23 hours between noon and noon the following day. If you want to correctly determine the number of hours from time A and time B, you need to first translate each to their UTC equivalents before calculating the TimeSpan.

This is covered by a blog post i wrote that further explains TimeSpan, and includes a link to an even more extensive MS article on the topic.

*Clarification: Either assignment will store the current time. If you were to load two variables one via DateTime.Now() and the other via DateTime.UtcNow() the TimeSpan difference between the two would be milliseconds, not hours assuming you are in a timezone hours away from GMT. As noted below, printing out their String values would display different strings.

Noctis
  • 10,865
  • 3
  • 38
  • 74
Carl Camera
  • 4,634
  • 2
  • 23
  • 19
  • 1
    Regarding "load a variable with DateTime.Now or DateTime.UtcNow -- the assignment is identical": This may need to be clarified? As I sit here in the EDT timezone (UTC -4), I assigned two variables to DateTime.UtcNow and DateTime.Now respectively, and then printed their values with ToString(). The displayed values were 4 hours apart -- not "identical." – Jon Schneider May 19 '15 at 14:40
  • 2
    @JonSchneider, I believe you are correct. The statement: "the assignment is identical" is not true. ToString() is probably not the best way to test that, because it *could* display equal dates differently (like Java does). Comparison functions are a better test, and show they are indeed not equal. – Ted Bigham May 20 '15 at 17:55
  • Clarification to my "identical" statement: Load one variable via DateTime.Now and another with DateTime.UtcNow and then print the TimeSpan difference. The difference will be milliseconds and not hours assuming you are hours away from GMT. – Carl Camera Dec 15 '16 at 20:11
21

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.

Noctis
  • 10,865
  • 3
  • 38
  • 74
Ted Bigham
  • 3,872
  • 1
  • 21
  • 29
8

DateTime has no idea what time zones are. It always assumes you're at your local time. UtcNow only means "Subtract my timezone from the time".

If you want to use timezone-aware dates, use DateTimeOffset, which represents a date/time with a timezone. I had to learn that the hard way.

Omer van Kloeten
  • 11,272
  • 9
  • 38
  • 53
  • 9
    To be entirely precise (and avoid people from using Now over UtcNow for performance reasons), it's the other way around: Now adds the time zone to UtcNow and is in fact a magnitude slower. – mafu Feb 09 '12 at 15:30
5

The "simple" answer to the question is:

DateTime.Now returns a DateTime value representing the current, system time (in whatever time zone the system is running in). The DateTime.Kind property will be DateTimeKind.Local

DateTime.UtcNow returns a DateTime value representing the current Universal Co-ordinated Time (aka UTC) which will be the same regardless of the system's time zone. The DateTime.Kind property will be DateTimeKind.Utc

PapillonUK
  • 631
  • 7
  • 20
4

Just a little addition to the points made above: the DateTime struct also contains a little known field called Kind (at least, I did not know about it for a long time). It is basically just a flag indicating whether the time is local or UTC; it does not specify the real offset from UTC for local times. Besides the fact that it indicates with what intentions the stuct was constructed, it also influences the way how the methods ToUniversalTime() and ToLocalTime() work.

Jan Zich
  • 13,955
  • 17
  • 58
  • 72
3

A little bit late to the party, but I found these two links (4guysfromrolla) to be very useful:

Using Coordinated Universal Time (UTC) to Store Date/Time Values

Advice for Storing and Displaying Dates and Times Across Different Time Zones

Sorin Comanescu
  • 4,581
  • 2
  • 26
  • 36
1

DateTime.UtcNow is a continuous, single-valued time scale, whereas DateTime.Now is not continuous or single-valued. The primary reason is Daylight Savings Time, which doesn't apply to UTC. So UTC never jumps forward or back an hour, whereas local time(DateTime.Now) does. And when it jumps backward, the same time value occurs twice.

1

DateTime.UtcNow is a Universal time scale omitting Daylight Savings Time. So UTC never changes due to DST.

But, DateTime.Now is not continuous or single-valued because it changes according to DST. Which means DateTime.Now, the same time value may occur twice leaving customers in a confused state.

ChaiVan
  • 71
  • 1
  • 5
1

The big difference :) is that DateTime.Now is not supported in SharePoint Workflow you must use DateTime.UtcNow

1

When you need a local time for the machine your application runs at (like CEST for Europe), use Now. If you want a universal time - UtcNow. It's just matter of your preferences - probably making a local website / standalone application you'd want to use the time user has - so affected by his/her timezone setting - DateTime.Now.

Just remember, for a website it's the timezone setting of the server. So if you're displaying the time for the user, either get his prefered timezone and shift the time (just save Utc time to database then, and modify it) or specify it's UTC. If you forget to do so, user can see something like: posted 3 minuses ago and then a time in the future near it :)

kender
  • 79,300
  • 24
  • 99
  • 144