Difference between System.DateTime.Now and System.DateTime.Today
.net, c#, date, datetime
Solution
`DateTime.Now` returns a `DateTime` value that consists of the local date and time of the computer where the code is running. It has `DateTimeKind.Local` assigned to its `Kind` property. It is equivalent to calling any of the following:
- `DateTime.UtcNow.ToLocalTime()`
- `DateTimeOffset.UtcNow.LocalDateTime`
- `DateTimeOffset.Now.LocalDateTime`
- `TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)`
- `TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)`
`DateTime.Today` returns a `DateTime` value that has the same year, month, and day components as any of the above expressions, but with the time components set to zero. It also has `DateTimeKind.Local` in its `Kind` property. It is equivalent to any of the following:
- `DateTime.Now.Date`
- `DateTime.UtcNow.ToLocalTime().Date`
- `DateTimeOffset.UtcNow.LocalDateTime.Date`
- `DateTimeOffset.Now.LocalDateTime.Date`
- `TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date`
- `TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local).Date`
Note that internally, the system clock is in terms of UTC, so when you call `DateTime.Now` it first gets the UTC time (via the `GetSystemTimeAsFileTime` function in the Win32 API) and then it converts the value to the local time zone. (Therefore `DateTime.Now.ToUniversalTime()` is more expensive than `DateTime.UtcNow`.)
Also note that `DateTimeOffset.Now.DateTime` will have similar values to `DateTime.Now`, but it will have `DateTimeKind.Unspecified` rather than `DateTimeKind.Local` - which could lead to other errors depending on what you do with it.
So, the simple answer is that `DateTime.Today` is equivalent to `DateTime.Now.Date`. But IMHO - You shouldn't use either one of these, or any of the above equivalents.
When you ask for `DateTime.Now`, you are asking for the value of the local calendar clock of the computer that the code is running on. But what you get back does not have any information about that clock! The best that you get is that `DateTime.Now.Kind == DateTimeKind.Local`. But whose local is it? That information gets lost as soon as you do anything with the value, such as store it in a database, display it on screen, or transmit it using a web service.
If your local time zone follows any daylight savings rules, you do not get that information back from `DateTime.Now`. In ambiguous times, such as during a "fall-back" transition, you won't know which of the two possible moments correspond to the value you retrieved with `DateTime.Now`. For example, say your system time zone is set to `Mountain Time (US & Canada)` and you ask for `DateTime.Now` in the early hours of November 3rd, 2013. What does the result `2013-11-03 01:00:00` mean? There are two moments of instantaneous time represented by this same calendar datetime. If I were to send this value to someone else, they would have no idea which one I meant. Especially if they are in a time zone where the rules are different.
The best thing you could do would be to use `DateTimeOffset` instead:
// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;
Now for the same scenario I described above, I get the value `2013-11-03 01:00:00 -0600` before the transition, or `2013-11-03 01:00:00 -0700` after the transition. Anyone looking at these values can tell what I meant.
I wrote a blog post on this very subject. Please read - The Case Against DateTime.Now.
Also, there are some places in this world (such as Brazil) where the "spring-forward" transition happens exactly at Midnight. The clocks go from 23:59 to 01:00. This means that the value you get for `DateTime.Today` on that date, does not exist! Even if you use `DateTimeOffset.Now.Date`, you are getting the same result, and you still have this problem. It is because traditionally, there has been no such thing as a `Date` object in .Net. So regardless of how you obtain the value, once you strip off the time - you have to remember that it doesn't really represent "midnight", even though that's the value you're working with.
If you really want a fully correct solution to this problem, the best approach is to use NodaTime. The `LocalDate` class properly represents a date without a time. You can get the current date for any time zone, including the local system time zone:
using NodaTime;
...
Instant now = SystemClock.Instance.Now;
DateTimeZone zone1 = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate todayInTheSystemZone = now.InZone(zone1).Date;
DateTimeZone zone2 = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDate todayInTheOtherZone = now.InZone(zone2).Date;
If you don't want to use Noda Time, there is now another option. I've contributed an implementation of a date-only object to the .Net CoreFX Lab project. You can find the `System.Time` package object in their MyGet feed. Once added to your project, you will find you can do any of the following:
using System;
...
Date localDate = Date.Today;
Date utcDate = Date.UtcToday;
Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
Problem
Can anyone explain the difference between `System.DateTime.Now` and `System.DateTime.Today` in C#.NET? Pros and cons of each if possible.