Safely comparing local and universal DateTimes - c#

I just noticed what seems like a ridiculous flaw with DateTime comparison.
DateTime d = DateTime.Now;
DateTime dUtc = d.ToUniversalTime();
d == dUtc; // false
d.Equals(dUtc); //false
DateTime.Compare(d, dUtc) == 0; // false
It appears that all comparison operations on DateTimes fail to do any type of smart conversion if one is DateTimeKind.Local and one is DateTimeKind.UTC. Is the a better way to reliably compare DateTimes aside from always converting both involved in the comparison to utc time?

When you call .Equal or .Compare, internally the value .InternalTicks is compared, which is a ulong without its first two bits. This field is unequal, because it has been adjusted a couple of hours to represent the time in the universal time: when you call ToUniversalTime(), it adjusts the time with an offset of the current system's local timezone settings.
You should see it this way: the DateTime object represents a time in an unnamed timezone, but not a universal time plus timezone. The timezone is either Local (the timezone of your system) or UTC. You might consider this a lack of the DateTime class, but historically it has been implemented as "number of ticks since 1970" and doesn't contain timezone info.
When converting to another timezone, the time is — and should be — adjusted. This is probably why Microsoft chose to use a method as opposed to a property, to emphasize that an action is taken when converting to UTC.
Originally I wrote here that the structs are compared and the flag for System.DateTime.Kind is different. This is not true: it is the amount of ticks that differs:
t1.Ticks == t2.Ticks; // false
t1.Ticks.Equals(t2.Ticks); // false
To safely compare two dates, you could convert them to the same kind. If you convert any date to universal time before comparing you'll get the results you're after:
DateTime t1 = DateTime.Now;
DateTime t2 = someOtherTime;
DateTime.Compare(t1.ToUniversalTime(), t2.ToUniversalTime()); // 0
DateTime.Equals(t1.ToUniversalTime(), t2.ToUniversalTime()); // true
Converting to UTC time without changing the local time
Instead of converting to UTC (and in the process leaving the time the same, but the number of ticks different), you can also overwrite the DateTimeKind and set it to UTC (which changes the time, because it is now in UTC, but it compares as equal, as the number of ticks is equal).
var t1 = DateTime.Now
var t2 = DateTime.SpecifyKind(t1, DateTimeKind.Utc)
var areEqual = t1 == t2 // true
var stillEqual = t1.Equals(t2) // true
I guess that DateTime is one of those rare types that can be bitwise unequal, but compare as equal, or can be bitwise equal (the time part) and compare unequal.
Changes in .NET 6
In .NET 6.0, we now have TimeOnly and DateOnly. You can use these to store "just the time of day", of "just the date of the year". Combine these in a struct and you'll have a Date & Time struct without the historical nuisances of the original DateTime.
Alternatives
Working properly with DateTime, TimeZoneInfo, leap seconds, calendars, shifting timezones, durations etc is hard in .NET. I personally prefer NodaTime by Jon Skeet, which gives control back to the programmer in a meaningful an unambiguous way.
Often, when you’re not interested in the timezones per se, but just the offsets, you can get by with DateTimeOffset.
This insightful post by Jon Skeet explains in great depth the troubles a programmer can face when trying to circumvent all DateTime issues when just storing everything in UTC.
Background info from the source
If you check the DateTime struct in the .NET source, you'll find a note that explains how originally (in .NET 1.0) the DateTime was just the number of ticks, but that later they added the ability to store whether it was Universal or Local time. If you serialize, however, this info is lost.
This is the note in the source:
// This value type represents a date and time. Every DateTime
// object has a private field (Ticks) of type Int64 that stores the
// date and time as the number of 100 nanosecond intervals since
// 12:00 AM January 1, year 1 A.D. in the proleptic Gregorian Calendar.
//
// Starting from V2.0, DateTime also stored some context about its time
// zone in the form of a 3-state value representing Unspecified, Utc or
// Local. This is stored in the two top bits of the 64-bit numeric value
// with the remainder of the bits storing the tick count. This information
// is only used during time zone conversions and is not part of the
// identity of the DateTime. Thus, operations like Compare and Equals
// ignore this state. This is to stay compatible with earlier behavior
// and performance characteristics and to avoid forcing people into dealing
// with the effects of daylight savings. Note, that this has little effect
// on how the DateTime works except in a context where its specific time
// zone is needed, such as during conversions and some parsing and formatting
// cases.

To deal with this, I created my own DateTime object (let's call it SmartDateTime) that contains the DateTime and the TimeZone. I override all operators like == and Compare and convert to UTC before doing the comparison using the original DateTime operators.

Related

C# UTC conversion and Daylight Saving Time in game save

So, I've made a game in which it is required to check the time when saving and loading.
The relevant chunk of loading code:
playerData = save.LoadPlayer();
totalSeconds = playerData.totalSeconds;
System.DateTime stamp = System.DateTime.MinValue;
if (!System.DateTime.TryParse(playerData.timeStamp, out stamp)) {
playerData.timeStamp = System.DateTime.UtcNow.ToString("o");
stamp = System.DateTime.Parse(playerData.timeStamp);
}
stamp = stamp.ToUniversalTime();
loadStamp = System.DateTime.UtcNow;
long elapsedSeconds = (long)(System.DateTime.UtcNow - stamp).TotalSeconds;
if (elapsedSeconds < 0) {
ui.Cheater();
}
Obviously, all this does is check to see if the currently saved timestamp can be parsed - if so, we make sure it's UTC, if not, we set the stamp to the current time and continue. If the elapsed time between the loaded timestamp and current time is negative, we know the player has messed with their clock to exploit the system.
The potential problem arises when the clocks move an hour back for DST.
This is the relevant code in the save function, if it matters:
if (loadStamp == System.DateTime.MinValue) {
loadStamp = System.DateTime.UtcNow;
}
playerData.timeStamp = loadStamp.AddSeconds(sessionSeconds).ToString("o");
My question is:
Will this currently used method potentially cause any problems when the clocks move back and falsely deem players cheaters?
Thank you in advance.
EDIT:
Forgot to add that it seems to not cause any problems on the computer when the time is set to when the clocks move back, but the game is mobile. Again, if that matters at all. Not quite sure. I've not done much with time-based rewards and stuff in games thus far.
Update I have significantly updated this answer in respect of comments made by #theMayer and the fact that while I was wrong, it may have highlighted a bigger issue.
I believe there is an issue here in the fact that the code is reading the UTC time in, converting it to local time, then converting it back to UTC.
The save routine records the value of loadStamp expressed with the Round Trip format specifier o, and as loadStamp is always set from DateTime.UtcNow, the value stored in the file will always be a UTC time with a trailing "Z" indicating UTC time.
For example:
2018-02-18T01:30:00.0000000Z ( = 2018-02-17T23:30:00 in UTC-02:00 )
The issue was reported in the Brazil time zone, with a UTC offset of UTC-02:00 (BRST) until 2018-02-18T02:00:00Z and a UTC offset of UTC-03:00 (BRT) after.
The code reaches this line:
if (!System.DateTime.TryParse(playerData.timeStamp, out stamp)) {
DateTime.TryParse() (which uses the same rules as DateTime.Parse()) will encounter this string. It will then convert the UTC time into a local time, and set stamp to equal:
2018-02-17T23:30:00 DateTimeKind.Local
The code then reaches:
stamp = stamp.ToUniversalTime();
At this point, stamp should represent an Ambiguous time, i.e. one that exists as a valid BRST and a valid BRT time, and MSDN states:
If the date and time instance value is an ambiguous time, this method assumes that it is a standard time. (An ambiguous time is one that can map either to a standard time or to a daylight saving time in the local time zone)
This means that .NET could be changing the UTC value of any ambiguous DateTime values that are converted to Local time and back again.
Although the documentation states this clearly, I have been unable to reproduce this behaviour in the Brazilian time zone. I am still investigating this.
My approach to this type of issue is to use the DateTimeOffset type instead of DateTime. It represents a point-in-time that is irrelevant of local time, time zones, or Daylight Savings.
An alternative approach to closing this hole would be to change:
if (!System.DateTime.TryParse(playerData.timeStamp, out stamp)) {
playerData.timeStamp = System.DateTime.UtcNow.ToString("o");
stamp = System.DateTime.Parse(playerData.timeStamp);
}
stamp = stamp.ToUniversalTime();
to
if (!System.DateTime.TryParse(playerData.timeStamp, null, DateTimeStyles.RoundtripKind, out stamp)) {
stamp = System.DateTime.UtcNow;
playerData.timeStamp = stamp.ToString("o");
}
Again assuming that the saved playerData.timeStamp will always be from a UTC date and therefore be in "Z" timezone, adding the DateTimeStyles.RoundtripKind should mean it gets parsed straight into DateTimeKind.Utc and not converted into Local time as DateTimeKind.Local. It also eliminates the need to call ToUniversalTime() on it to convert it back.
Hope this helps
On the surface, there does not appear to be anything obviously wrong with this code.
When doing DateTime comparison operations, it is important to ensure that the time zone of the compared DateTime's are consistent. The framework only compares the values of the instances, irrespective of whatever time zone you think they are in. It is up to you to ensure consistent time zones between DateTime instances. It looks like that is being done in this case, as times are converted from local to UTC prior to being compared with other UTC times:
stamp = stamp.ToUniversalTime();
elapsedSeconds = (long)(System.DateTime.UtcNow - stamp).TotalSeconds;
Some Caveats
One item that often trips people up is that the time value is repeatedly queried (each call to DateTime.UtcNow) - which could result in different values each time. However, the difference would be infinitesimal, and most of the time zero as this code will execute faster than the resolution of the processor clock.
Another fact, which I brought up in the comments, the "Round Trip Format Specifier" used to write the DateTime to string is intended to preserve time zone information - in this case, it should add a "Z" to the time to denote UTC. Upon conversion back (via TryParse), the parser will convert this time from the UTC to a local time if the Z is present. This can be a significant gotcha as it results in an actual DateTimevalue that is different from the one serialized to the string, and in a way is contrary to every other way that the .NET framework handles DateTime's (which is to ignore time zone info). If you have a case where the "Z" is not present in the incoming string, but the string is otherwise UTC, then you have a problem there because it will be comparing a UTC time whose value has been adjusted a second time (thus making it the time of UTC +2).
It should also be noted that in .Net 1.1, DateTime.ToUniversalTime() is NOT an idempotent function. It will offset the DateTime instance by the difference in time zone between the local time zone and UTC each time it is called. From the documentation:
This method assumes that the current DateTime holds the local time value, and not a UTC time. Therefore, each time it is run, the current method performs the necessary modifications on the DateTime to derive the UTC time, whether the current DateTime holds the local time or not.
Programs using a later version of the framework may or may not have to worry about this, depending on usage.

Subtracting UTC and non-UTC DateTime in C#

I assumed that when subtracting 2 datetimes the framework will check their timezone and make the appropriate conversions.
I tested it with this code:
Console.WriteLine(DateTime.Now.ToUniversalTime() - DateTime.UtcNow.ToUniversalTime());
Console.WriteLine(DateTime.Now.ToUniversalTime() - DateTime.UtcNow);
Console.WriteLine(DateTime.Now - DateTime.UtcNow);
Output:
-00:00:00.0020002
-00:00:00.0020001
01:59:59.9989999
To my surprise, DateTime.Now - DateTime.UtcNow does not make the appropriate conversion automatically. At the same time, DateTime.UtcNow is the same as DateTime.UtcNow.ToUniversalTime(), so obviously there is some internal flag that indicates the time zone.
Is that correct, does that framework not perform the appropriate timezone conversion automatically, even if the information is already present? If so, is applying ToUniversalTime() safe for both UTC and non-UTC datetimes, i.e. an already UTC datetime will not be incorrectly corrected by ToUniversalTime()?
The type System.DateTime does not hold time zone information, only a .Kind property that specifies whether it is Local or UTC. But before .NET 2.0, there was not even a .Kind property.
When you subtract (or do other arithmetic, like == or >, on) two DateTime values, their "kinds" are not considered at all. Only the numbers of ticks are considered. This gives compatibility with .NET 1.1 when no kinds existed.
The functionality you ask for (and expect) is in the newer and richer type System.DateTimeOffset. In particular, if you do the subtraction DateTimeOffset.Now - DateTimeOffset.UtcNow you get the result you want. The DateTimeOffset structure does not have a local/UTC flag; instead, it holds the entire time zone, such as +02:00 in your area.
The framework does nothing with the date if it is already UTC:
internal static DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfoOptions flags)
{
if (dateTime.Kind == DateTimeKind.Utc)
{
return dateTime;
}
CachedData cachedData = s_cachedData;
return ConvertTime(dateTime, cachedData.Local, cachedData.Utc, flags, cachedData);
}

DateTime.Ticks property value

Shouldn't the value of DateTime.Now.Ticks be the same as DateTime.UtcNow.Ticks? I checked their values and found that the difference represents my current time zone offset from UTC. What am I missing here?
This is part of how the objects were designed.
In other libraries and languages (for example, JavaScript's Date type), the value is bound to UTC, and usually uses an epoch of 1970-01-01.
But in .NET, the Ticks value is related to the same frame of reference that the Years, Months, Days, and other properties are based on. It uses an epoch of 0001-01-01.
In DateTime, there's a property called Kind:
If the kind is DateTimeKind.Utc, then you know the value is related to UTC.
If the kind is DateTimeKind.Local, then you know the value is related to the local time zone.
If the kind is DateTimeKind.Unspecified, then you have no idea what time zone reference you have. You simply have a date and time.
You see the difference between DateTime.UtcNow.Ticks and DateTime.Now.Ticks as your current time zone offset, because DateTime.Now has Local kind, while DateTime.UtcNow has Utc kind. So the ticks of DateTime.Now are based on your local time zone, while ticks from DateTime.UtcNow are based on UTC.
The DateTimeOffset type can be used to counteract this problem. The Ticks are still relative to the value shown, but the Offset can be used to always adjust these ticks back to a UTC frame of reference.
If you don't like this, as many do not, an alternative is to use types from the Noda Time library.
By the way, I cover this information in even greater detail, and compare it to other programming languages in my Pluralsight course, Date and Time Fundamentals.
It's different because the time zones are different.

Converting datetime to time in C# / ASP.NET

I am trying to insert time on my asp.net project.
RequestUpdateEmployeeDTR requestUpdateEmployeeDTR = new RequestUpdateEmployeeDTR();
requestUpdateEmployeeDTR.AttendanceDeducID = int.Parse(txtAttendanceDeducID.Text);
requestUpdateEmployeeDTR.TimeInChange = txtTimeOutChange.Text;
requestUpdateEmployeeDTR.TimeOutChange = txtTimeOutChange.Text;
TimeInChange and TimeOutChange are DateTime data types. But I am inserting a time data type. How can I convert that into a time data type using C#? Thanks!
The .NET Framework does not have a native Time data type to represent a time of day. You will have to decide between one of the three following options:
Option 1
Use a DateTime type, and ignore the date portion. Pick a date that's outside of a normal range of values for your application. I typically use 0001-01-01, which is conveniently available as DateTime.MinValue.
If you are parsing a time from a string, the easiest way to do this is with the DateTimeStyles.NoCurrentDateDefault option. Without this option, it would use today's date instead of the min date.
DateTime myTime = DateTime.Parse("12:34", CultureInfo.InvariantCulture,
DateTimeStyles.NoCurrentDateDefault);
// Result: 0001-01-01 12:34:00
Of course, if you prefer to use today's date, you can do that. I just think it confuses the issue because you might be looking to apply this to some other date entirely.
Note that once you have a DateTime value, you can use the .TimeOfDay property to get at just the time portion, represented as a TimeSpan, which leads to option 2...
Option 2
Use a TimeSpan type, but be careful in how you interpret it. Understand that TimeSpan is first and foremost a type for representing an elapsed duration of time, not a time of day. That means it can store more than 24 hours, and it can also store negative values to represent moving backwards in time.
When you use it as a time of day, you might be inclined to think of it as "elapsed time since midnight". This, however, will get you into trouble because there are days where midnight does not exist in the local time zone.
For example, October 20th 2013 in Brazil started at 1:00 AM due to daylight saving time. So a TimeSpan of 8:00 on this day would actually have been only 7 hours elapsed since 1:00, not 8 hours elapsed since midnight.
Even in the United States, for locations that use daylight saving time, this value is misleading. For example, November 3rd 2013 in Los Angeles had a duplicated hour for when DST rolled back. So a TimeSpan of 8:00 on this day would actually had 9 hours elapsed since midnight.
So if you use this option, just be careful to treat it as the representative time value that matches a clock, and not as "time elapsed since midnight".
You can get it directly from a string with the following code:
TimeSpan myTime = TimeSpan.Parse("12:34", CultureInfo.InvariantCulture);
Option 3
Use a library that has a true "time of day" type. You'll find this in Noda Time, which offers a much better API for working with date and time in .NET.
The type that represents a "time of day" is called LocalTime, and you can get one from a string like this:
var pattern = LocalTimePattern.CreateWithInvariantCulture("HH:mm");
LocalTime myTime = pattern.Parse("12:34").Value;
Since it appears from your question that you are working with time and attendance data, I strongly suggest you use Noda Time for all your date and time needs. It will force you to put more thought into what you are doing. In the process, you will avoid the pitfalls that can come about with the built-in date/time types.
If you are storing a Time type in your database (such as SQL server), that gets translated as a TimeSpan in .Net. So if you go with this option, you'll need to convert the LocalTime to a TimeSpan as follows:
TimeSpan ts = new TimeSpan(myTime.TickOfDay);

Difference between System.DateTime.Now and System.DateTime.Today

Can anyone explain the difference between System.DateTime.Now and System.DateTime.Today in C#.NET? Pros and cons of each if possible.
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);
Time. .Now includes the 09:23:12 or whatever; .Today is the date-part only (at 00:00:00 on that day).
So use .Now if you want to include the time, and .Today if you just want the date!
.Today is essentially the same as .Now.Date
The DateTime.Now property returns the current date and time, for example 2011-07-01 10:09.45310.
The DateTime.Today property returns the current date with the time compnents set to zero, for example 2011-07-01 00:00.00000.
The DateTime.Today property actually is implemented to return DateTime.Now.Date:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
DateTime.Today represents the current system date with the time part set to 00:00:00
and
DateTime.Now represents the current system date and time
I thought of Adding these links -
A brief History of DateTime - By Anthony Moore by BCL team
Choosing between Datetime and DateTime Offset - by MSDN
Do not forget SQL server 2008 onwards has a new Datatype as DateTimeOffset
The .NET Framework includes the DateTime, DateTimeOffset, and
TimeZoneInfo types, all of which can be used to build applications
that work with dates and times.
Performing Arithmetic Operations with Dates and Times-MSDN
Coming back to original question , Using Reflector i have explained the difference in code
public static DateTime Today
{
get
{
return DateTime.Now.Date; // It returns the date part of Now
//Date Property
// returns same date as this instance, and the time value set to 12:00:00 midnight (00:00:00)
}
}
private const long TicksPerMillisecond = 10000L;
private const long TicksPerDay = 864000000000L;
private const int MillisPerDay = 86400000;
public DateTime Date
{
get
{
long internalTicks = this.InternalTicks; // Date this instance is converted to Ticks
return new DateTime((ulong) (internalTicks - internalTicks % 864000000000L) | this.InternalKind);
// Modulo of TicksPerDay is subtracted - which brings the time to Midnight time
}
}
public static DateTime Now
{
get
{
/* this is why I guess Jon Skeet is recommending to use UtcNow as you can see in one of the above comment*/
DateTime utcNow = DateTime.UtcNow;
/* After this i guess it is Timezone conversion */
bool isAmbiguousLocalDst = false;
long ticks1 = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks;
long ticks2 = utcNow.Ticks + ticks1;
if (ticks2 > 3155378975999999999L)
return new DateTime(3155378975999999999L, DateTimeKind.Local);
if (ticks2 < 0L)
return new DateTime(0L, DateTimeKind.Local);
else
return new DateTime(ticks2, DateTimeKind.Local, isAmbiguousLocalDst);
}
}
DateTime dt = new DateTime();// gives 01/01/0001 12:00:00 AM
DateTime dt = DateTime.Now;// gives today date with current time
DateTime dt = DateTime.Today;// gives today date and 12:00:00 AM time
DateTime.Today is DateTime.Now with time set to zero.
It is important to note that there is a difference between a DateTime value, which represents the number of ticks that have elapsed since midnight of January 1, 0000, and the string representation of that DateTime value, which expresses a date and time value in a culture-specific-specific format:
https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx
DateTime.Now.Ticks is the actual time stored by .net (essentially UTC time), the rest are just representations (which are important for display purposes).
If the Kind property is DateTimeKind.Local it implicitly includes the time zone information of the local computer. When sending over a .net web service, DateTime values are by default serialized with time zone information included, e.g. 2008-10-31T15:07:38.6875000-05:00, and a computer in another time zone can still exactly know what time is being referred to.
So, using DateTime.Now and DateTime.Today is perfectly OK.
You usually start running into trouble when you begin confusing the string representation with the actual value and try to "fix" the DateTime, when it isn't broken.
DateTime.Now.ToShortDateString() will display only the date part

Categories