Create Instant using a negative year - c#

I am trying to create an Instant based upon a B.C.E. year in the Gregorian calendar.
Here is what I have so far:
Instant.FromDateTimeOffset(new DateTimeOffset(-1000, 10, 01,
0, 0, 0, 0,
new System.Globalization.GregorianCalendar(),
new TimeSpan()));
I get the error:
An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
Additional information: Year, Month, and Day parameters describe an un-representable DateTime.
Edit
Doing some research on NodaTime, I can see that it does have the ability to represent the dates I want, as it can accept negative ticks from the Unix epoch:
The Noda Time Instant type represents a point on this global timeline: the number of ticks which have elapsed since the Unix epoch. The value can be negative for dates and times before 1970 of course - the range of supported dates is from around 27000 BCE to around 31000 CE in the Gregorian calendar.
- http://nodatime.org/1.3.x/userguide/concepts.html
So I would like to know how to do this using NodaTime rather than create my own implementation, as is mentioned here for instance.

The correct way to create a BCE date in Noda Time is like this:
LocalDate date = new LocalDate(Era.BeforeCommon, 1000, 10, 1);
This gives a LocalDate object, which is representative of just having a date. You asked for an Instant, which represents an exact point in time. These are two very different concepts.
In order to get an Instant from a LocalDate, one has to make a few assertions:
What time of day did it occur?
What time zone was it in?
Is the time valid and unambiguous on that date within that zone?
Let's pick midnight for the time and UTC for the time zone:
Instant instant = date.AtMidnight().InUtc().ToInstant();
Since we chose UTC, we didn't have to address the valid/unambiguous question. With other zones, we would use one of the InZone methods instead of InUtc.
Also - you can indeed create an Instant directly (as Caramiriel showed), but be careful. Year 1 BCE is represented by year 0, so if you want 1000 BCE, you'd have to pass -999, not -1000.
Instant instant = Instant.FromUtc(-999, 10, 1, 0, 0, 0);
Again, this assumes the time at midnight and the UTC time zone.
Finally, keep in mind that none of these calendar systems or time zones actually existed during that time period, and usually when working with dates so old, the time part is not very accurate or relevant. Therefore, I recommend you attempt to only work in terms of LocalDate objects, and not use Instant at all, if you can.

Related

Why does order of independent operations (Add and ToLocalTime/ToUniversalTime) on DateTime changes the outcome?

These two lines produces the same result (results are in my timezone) which is expected:
new DateTime(1970, 1, 1).ToLocalTime().AddHours(10000) // [21.02.1971 17:00:00]
new DateTime(1970, 1, 1).AddHours(10000).ToLocalTime() // [21.02.1971 17:00:00]
Now these two lines produces two different results:
new DateTime(1970, 1, 1).ToLocalTime().AddHours(100000) // [29.05.1981 17:00:00]
new DateTime(1970, 1, 1).AddHours(100000).ToLocalTime() // [29.05.1981 18:00:00]
That seem really strange and I cannot quite understand why this is happening. I know Jon Skeet would argue that we should not use DateTime at all since it's not good enough and use nodatime instead, but out of curiosity it's interesting to know why exactly is this happening.
Logically the point in time does not change depending on the order of operation and it's still the same time, though apparently it is not in C#.
P.S. ToUniveralTime behaves the same way and produces 2 different results in the second example (off by one hour).
I'm assuming you're in the UK (where we spent the winter on UTC, but switch to UTC+1 in the summer). Therefore at midnight on 1/1/1970 we're on UTC.
new DateTime(1970, 1, 1).ToLocalTime() does nothing, except changes Kind to Local, because DateTime assumes that we specified a point in time in UTC. We then add 10,000 hours, which brings us to a point in winter time.
new DateTime(1970, 1, 1).AddHours(10,000) also brings us to a point in winter time UTC, so .ToLocalTime() again does nothing, except change Kind to Local.
However, things get different when we add 100,000 hours, since that brings us to a point after daylight savings kicks in.
new DateTime(1970, 1, 1).ToLocalTime().AddHours(100000) changes Kind to Local as before, and then adds 100,000 hours's worth of ticks. There's no appreciation that we moved from UTC to UTC+1.
new DateTime(1970, 1, 1).AddHours(100000) however brings us to a point in time where local time and UTC differ, because we're after the 29th March 1981 and daylight savings has kicked in. .ToLocalTime() therefore spots that there's a 1-hour difference and adds it, resulting in a time which is 1 hour ahead.
It's worth remember how DateTime behaves. It represents an instant in time - a number of ticks since an epoch. It also has a Kind property, which says whether that time is based on local time, UTC, or is "Unspecified" (i.e. you haven't told it).
For example, new DateTime(1980, 4, 1, 0, 0, 0, DateTimeKind.Local) (I chose a date after DST), and new DateTime(1980, 4, 1, 0, 0, 0, DateTimeKind.Utc) have the same value for their Ticks property, and they print the same string. However, calling .ToLocalTime() does different things: in the first case it does nothing (because the DateTime is already in local time), but in the second it adds an hour's worth of ticks to the DateTime.
So remember, always keep track of what Kind is, and be aware of the effect that it has when converting between UTC/local time. DateTime itself isn't particularly smart, but the timezone conversion methods do have a lot of special-case logic around Kind which can throw you.
I'd argue that you should probably be using DateTimeOffset instead of DateTime - that shows you what timezone you're currently in, and does away with the woolly notions of "Unspecified" and "Whatever timezone my PC is in". Try repeating this experiment with DateTimeOffsets.

Does calling DateTime.AddDays with a whole number always leave the time unchanged?

Consider the following code which attempts to get a DateTime that's equivalent to the local time "midnight yesterday":
DateTime midnightYesterday = DateTime.Today.AddDays(-1.0d);
Will this always result in a DateTime with a time component of 00:00:00 -- regardless of any corner cases such as leap days, leap seconds, or what the local time zone is?
More generally: Does calling DateTime.AddDays, passing a whole number as a parameter, always result in a DateTime being returned that has the exact same time component as the original Datetime?
The MSDN documentation for DateTime.AddDays does not address this specific question.
DateTime does not account for leap seconds. You can read this article from which you will see that because of this it doesn't really support UTC. Documentation states that:
Time values are measured in 100-nanosecond units called ticks, and a
particular date is the number of ticks since 12:00 midnight, January
1, 0001 A.D. (C.E.) in the GregorianCalendar calendar (excluding ticks
that would be added by leap seconds)
About daylight saving time documentation states the following:
Conversion operations between time zones (such as between UTC and
local time, or between one time zone and another) take daylight saving
time into account, but arithmetic and comparison operations do not.
That means that adding days (which is arithmetic operation) to DateTime instance, even if it has kind Local (so represents time in local timezone) does not take DST into account. That makes performing any arithmetic operations on datetimes with kind Local a really bad idea. If you need to do that with date times - first convert it to UTC (that has no notion of DST), perform operation then convert back to local (conversion as stated above does take DST into account).
You can also look at source code to see that datetime value is stored as a number internally (number of ticks) and adding days just adds fixed value to that number. Calculating hour\minute\second use that value and perform fixed operations (just a division) to obtain target value. None of those operations account for anything like leap seconds, time zones or anything else. So the answer to your question is yes.

.Net DateTime with local time and DST

I'm afraid I don't really understand how .Net's DateTime class handles local timestamps (I live in Germany, so my locale is de_DE). Perhaps someone can enlighten me a bit ;-)
The DateTime constructor can be called with year, month etc. parameters. Additionally a DateTimeKind value of Local, Utc, or Unspecified (=default) can be provided.
Example:
DateTime a = new DateTime(2015, 03, 29, 02, 30, 00, DateTimeKind.Local);
DateTime b = new DateTime(2015, 03, 29, 02, 30, 00, DateTimeKind.Utc);
DateTime c = new DateTime(2015, 03, 29, 02, 30, 00, DateTimeKind.Unspecified);
DateTime d = new DateTime(2015, 03, 29, 02, 30, 00);
Per definition, values c and d are identical. But if I compare all against each other, all four are identical. Inspecting the objects in VS's debugger shows that the Ticks value (and InternalTicks as well) is the same for all. However, internal dateData values are different, but are obviously ignored by the comparison operator.
As you might have noticed, I constructed a value for March 29th this year, 02:30 AM. This moment in time does not exist in our timezone as it is skipped by switching to Daylight Saving Time. So I had expected to get an exception for constructing object a, but this did not happen.
Furthermore, DateTime has a method ToUniversalTime() that converts a value that is interpreted as local time to the equivalent UTC value. For testing, I ran a loop as follows:
DateTime dt = new DateTime(2015, 03, 29, 01, 58, 00, DateTimeKind.Local);
DateTime dtEnd = new DateTime(2015, 03, 29, 03, 03, 00, DateTimeKind.Local);
while (dt < dtEnd)
{
Log(" Localtime " + dt + " converted to UTC is " + dt.ToUniversalTime());
dt = dt.AddMinutes(1);
}
The result is:
Localtime 29.03.2015 01:58:00 converted to UTC is 29.03.2015 00:58:00
Localtime 29.03.2015 01:59:00 converted to UTC is 29.03.2015 00:59:00
Localtime 29.03.2015 02:00:00 converted to UTC is 29.03.2015 01:00:00
Localtime 29.03.2015 02:01:00 converted to UTC is 29.03.2015 01:01:00
Localtime 29.03.2015 02:02:00 converted to UTC is 29.03.2015 01:02:00
...
Localtime 29.03.2015 02:58:00 converted to UTC is 29.03.2015 01:58:00
Localtime 29.03.2015 02:59:00 converted to UTC is 29.03.2015 01:59:00
Localtime 29.03.2015 03:00:00 converted to UTC is 29.03.2015 01:00:00
Localtime 29.03.2015 03:01:00 converted to UTC is 29.03.2015 01:01:00
Localtime 29.03.2015 03:02:00 converted to UTC is 29.03.2015 01:02:00
So, .Net has no problem converting non-existing timestamps from local time to UTC. Also, adding a minute to an existing local timestamp is not local-aware and gives a non-existing timestamp.
As a result, adding 64 single minutes yields, after conversion, a UTC timestamp that is only 4 minutes larger than before.
In other words, converting between local time and UTC should be a bijection, giving a one-to-one correspondence between legal timestamp values.
To cut a long story short: How do I handle this correctly the intended way (according to .Net)? What is the sense of having DateTimeKind if it is not taken into account correctly? I don't even dare to ask how leap seconds (at 23:59:60) are handled ;-)
Mike's answer is good. Yes, DateTimeOffset is almost always prefered over DateTime (but not for all scenarios), and Noda Time is vastly superior in many regards. However, I can add some more details to address your questions and observations.
First, MSDN has this to say:
UTC time is suitable for calculations, comparisons, and storing dates and time in files. Local time is appropriate for display in user interfaces of desktop applications. Time zone-aware applications (such as many Web applications) also need to work with a number of other time zones.
...
Conversion operations between time zones (such as between UTC and local time, or between one time zone and another) take daylight saving time into account, but arithmetic and comparison operations do not.
From this we can conclude that the test you provided is not valid because it performs calculations using a local time. It is useful only in that it highlights how the API allows you to break its own documented guidelines. In general, since the time from 02:00 to just before 03:00 does not exist in the local time zone on that date, it's not likely to be encountered in the real world unless it was obtained mathematically, such as by a daily recurrence pattern that didn't take DST into account.
BTW, the part of Noda Time that addresses this is the ZoneLocalMappingResolver, which is used when converting a LocalDateTime to a ZonedDateTime via the localDateTime.InZone method. There are some reasonable defaults such as InZoneStrictly, or InZoneLeniently, but it's not just silently shifted like you illustrated with DateTime.
With regard to your assertion:
In other words, converting between local time and UTC should be a bijection, giving a one-to-one correspondence between legal timestamp values.
Actually, it's not a bijection. (By the definition of bijection on Wikipedia, it does not satisfy criteria 3 or 4.) Only conversion in the UTC-to-local direction is a function. Conversion in the local-to-UTC direction has a discontinuity in during the spring-forward DST transition, and has ambiguity during the fall-back DST transition. You may wish to review the graphs in the DST tag wiki.
To answer your specific questions:
How do I handle this correctly the intended way (according to .Net)?
DateTime dt = new DateTime(2015, 03, 29, 01, 58, 00, DateTimeKind.Local);
DateTime dtEnd = new DateTime(2015, 03, 29, 03, 03, 00, DateTimeKind.Local);
// I'm putting this here in case you want to work with a different time zone
TimeZoneInfo tz = TimeZoneInfo.Local; // you would change this variable here
// Create DateTimeOffset wrappers so the offset doesn't get lost
DateTimeOffset dto = new DateTimeOffset(dt, tz.GetUtcOffset(dt));
DateTimeOffset dtoEnd = new DateTimeOffset(dtEnd, tz.GetUtcOffset(dtEnd));
// Or, if you're only going to work with the local time zone, you can use
// this constructor, which assumes TimeZoneInfo.Local
//DateTimeOffset dto = new DateTimeOffset(dt);
//DateTimeOffset dtoEnd = new DateTimeOffset(dtEnd);
while (dto < dtoEnd)
{
Log(" Localtime " + dto + " converted to UTC is " + dto.ToUniversalTime());
// Math with DateTimeOffset is safe in instantaneous time,
// but it might not leave you at the desired offset by local time.
dto = dto.AddMinutes(1);
// The offset might have changed in the local zone.
// Adjust it by either of the following (with identical effect).
dto = TimeZoneInfo.ConvertTime(dto, tz);
//dto = dto.ToOffset(tz.GetUtcOffset(dto));
}
What is the sense of having DateTimeKind if it is not taken into account correctly?
Originally, DateTime didn't have a kind. It behaved as if the kind was unspecified. DateTimeKind was added in .NET 2.0.
The main use case it covers is to prevent double conversion. For example:
DateTime result = DateTime.UtcNow.ToUniversalTime();
or
DateTime result = DateTime.Now.ToLocalTime();
Before .NET 2.0, these would both result in bad data, because the ToUniversalTime and ToLocalTime methods had to make the assumption that the input value was not converted. It would blindly apply the time zone offset, even when the value was already in the desired time zone.
There are a few other edge cases, but this is the main one. Also, there is a hidden fourth kind, which is used such that the following will still hold up with ambiguous values during the fall-back transition.
DateTime now = DateTime.Now;
Assert.True(now.ToUniversalTime().ToLocalTime() == now);
Jon Skeet has a good blog post about this, and you can also now see it discussed in the comments in the .NET Reference sources or in the new coreclr sources.
I don't even dare to ask how leap seconds (at 23:59:60) are handled ;-)
Leap seconds are actually not supported by .NET at all, including the current version of Noda Time. They're also not supported by any of the Win32 APIs, nor will you ever observe a leap second on the Windows clock.
In Windows, leap seconds are applied via NTP synchronization. The clock ticks by as if the leap second didn't occur, and during its next clock sync, the time is adjusted and it is absorbed. Here's what the next leap second will look like:
Real World Windows
-------------------- --------------------
2015-06-30T23:59:58Z 2015-06-30T23:59:58Z
2015-06-30T23:59:59Z 2015-06-30T23:59:59Z
2015-06-30T23:59:60Z 2015-07-01T00:00:00Z <-- one sec behind
2015-07-01T00:00:00Z 2015-07-01T00:00:01Z
2015-07-01T00:00:01Z 2015-07-01T00:00:02Z
2015-07-01T00:00:02Z 2015-07-01T00:00:02Z <-- NTP sync
2015-07-01T00:00:03Z 2015-07-01T00:00:03Z
I'm showing the sync at 2 seconds past midnight, but it could really be much later. Clock sync happens all the time, not just at leap seconds. The computer's local clock is not an ultra-precise instrument - it will drift, and periodically has to be corrected. You cannot assume the current time is always monotonically increasing - it could skip forward, or jump backward.
Also, the chart above isn't exactly accurate. I showed a hard shift in seconds, but in reality the OS will often introduce minor corrections by spreading out the effect of the change in several sub-second increments over a longer period of several seconds (a few milliseconds at a time).
At an API level, none of the APIs will support more than 59 in a seconds field. If they were to support it at all, it would probably just be during parsing.
DateTime.Parse("2015-06-30T23:59:60Z")
This will throw an exception. If it were to work, it would have to munge the extra leap second and either return the previous second (2015-06-30T23:59:59Z), or the next second (2015-07-01T00:00:00Z).
Yes, the DateTime type in .NET is major mess, as you can observe because it doesn't support the concepts of time-zones, multiple calendars and many other useful concepts such as intervals etc.
A little better is the DateTimeOffset type which adds time-zone offset information. The DateTimeOffset will allow you to more accurately represent the times you show in your question and comparisons will take the timezone offset into account. But this type is not perfect either. It still does not support true time zone information, only the offset. So it is not possible to perform complex DST calculations or to support advanced calendars.
For a much more thorough solution you can use NodaTime

Comparing time regardless of date

I have an object that has properties currently as DateTime.
The object is marked as valid within a time frame. The default being 00:00:00 to 23:59:59
The user enters the value in the UI and the property is set via:
new DateTime(DateTime.Now.Year,
DateTime.Now.Month,
DateTime.Now.Day,
model.Hours,
model.Minutes,
model.Seconds)
This is then converted to UTC when it hits the database.
Today's date is 29th August 2013. If a colleague in India runs this program it will store the data in the database as 28th August 2013 18:30:00 as they are 5.5 hours ahead of UTC so 29th August 2013 00:00:00 becomes yesterday.
When the logic tries to determine if the object is valid the logic is:
if (DateTime.UtcNow.TimeOfDay > model.MyPropertyFromDB.TimeOfDay)
We are trying to determine if the current time is within a range of 00:00:00 and 23:59:59
This fails as 14:00 (current time) is not greater than 18:30
What would be the best approach to compare just times?
Would storing the values as DateTimeOffSet help, is using ToLocal() ok?
Other considerations are that a user in India is using the app which is hosted in the UK so it needs to be timezone aware.
Thanks
Like others, I'm still unclear on exactly what you are wanting. But clearly, you shouldn't do this:
new DateTime(DateTime.Now.Year,
DateTime.Now.Month,
DateTime.Now.Day,
model.Hours,
model.Minutes,
model.Seconds)
That would be much better as:
DateTime.Today.Add(new TimeSpan(model.Hours, model.Minutes, model.Seconds))
But why are you doing this to begin with? Either of these would give you back the local date. I assume this is going to run on a server, so do you really want the time zone of the server to influence this result? Probably not. Please read: The Case Against DateTime.Now.
If you wanted the UTC date, you could do this:
DateTime.UtcNow.Date.Add(new TimeSpan(model.Hours, model.Minutes, model.Seconds))
That would at least be universally the same regardless of your server's time zone. But still, I don't think this is what you are after.
What's not clear is why is the user only entering the time while you are assigning the current date. If the date is relevant, then shouldn't the user enter it and it would be part of your model?
If the date is not relevant, then why are you storing it? You can use a TimeSpan type for the time value internally. You didn't say what your database is, but let's just guess that it is SQL Server, in which case you could use the time type on the field in the table.
I suppose it's possible that the date is relevant, but you want to control it, while the user takes control of providing the time. If that's the case, then you must know the time zone of the user (or the time zone of whatever the context is if it's not the user). Assuming you had a Windows time zone identifier (see the timezone tag wiki), then you could do something like this:
var tz = TimeZoneInfo.FindSystemTimeZoneById(theTimeZoneId);
var local = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz);
var dt = local.Date.Add(new TimeSpan(model.Hours, model.Minutes, model.Seconds));
If you don't have the time zone information, then this wouldn't be possible to solve.
As general advice, you might want to try using Noda Time instead of the built-in stuff. It's much better at helping you figure out this sort of thing. From the main page:
Noda Time is an alternative date and time API for .NET. It helps you to think about your data more clearly, and express operations on that data more precisely.
That appears to be directly the problem you are having here. If you want to clarify some of the questions I asked, I'd be happy to edit my answer and show you exactly how to do this with Noda Time.
Why your question is confusing
We are trying to determine if the current time is within a range of 00:00:00 and 23:59:59
All times are within that range. Well, maybe a value like 23:59:59.1 would be outside of it, but you aren't collecting fractional seconds in your model, so that's irrelevant. But why would you need to validate that? Maybe you are just trying to avoid numbers that aren't valid times at all? Like 99:99:99?
This fails as 14:00 (current time) is not greater than 18:30
Wait - you didn't say anything about comparing one time greater than another. 14:00 and 18:30 are both still in the range you specified.
What would be the best approach to compare just times?
Hard to answer. Are they both UTC times? Is one UTC and one is local? Are they both local? Do you know the time zone of the local times? Are you prepared to deal with ambiguous or invalid local times do to daylight saving time transitions?
Would storing the values as DateTimeOffSet help?
Perhaps, but you haven't given me enough information. It would help only if the date portion is relevant and the you get the correct offsets.
is using ToLocal() ok?
I would argue that no, it's not ok. Local in this context will give you the time zone of the server, which you probably don't want to introduce into your business logic.
So if I understand this correctly you have a time saved in UTC in the database and you are trying to determine whether it falls within a particular time frame? I'm not sure if you want the time frame in local time or UTC so here are both:
DateTime dbTime = model.MyPropertyFromDB;
TimeSpan minTime = new TimeSpan(0, 0, 0);
TimeSpan maxTime = new TimeSpan(23, 59, 59);
if (dbTime.TimeOfDay > minTime && dbTime.TimeOfDay < maxTime)
{
//Within time range (UTC)
}
if (dbTime.ToLocalTime().TimeOfDay > minTime && dbTime.ToLocalTime().TimeOfDay < maxTime)
{
//Within time range (local)
}
Edit: If you want to compare Now to a start and end time from an object in database:
TimeSpan now = DateTime.UtcNow.TimeOfDay;
TimeSpan startDate = model.startDate.TimeOfDay;
TimeSpan endDate = model.endDate.TimeOfDay;
if (now > startDate && now < endDate)
{
//Within time range (UTC)
}
I would say that the methodology being used here is fundamentally flawed and that you need to take a different approach.
new DateTime(DateTime.Now.Year, // Server date
DateTime.Now.Month,
DateTime.Now.Day,
model.Hours, // Local time
model.Minutes,
model.Seconds)
I can't see a way of 'normalising' the input in this way, unless you have a way of reliably knowing exactly which timezone a user is in. Simply, there's no easy way to turn a date built in this way into UTC.
My first question to you is, how is the model being passed from client to server? If you're using javascript/ajax then the solution should be fairly straightforward to solve by constructing the datetime object on the client (which will include their timezone data) and then rely on the browser to convert it to UTC for transit.
If you are using Razor\MVC then you can achieve a similar thing with forms encoding, except that you will need to call ToUTC on the server as the browser won't automatically fix the date for you for this media format.
Both methods require that you build a full datetime object on the client and then submit it, rather than trying to build it from seconds, minutes, hours on the server. You don't need to expose all this to the client of course, as long as the datetime is fully formed at the point of submission.
Once you've got a nice UTC datetime, you can extract just the time if you don't need the rest of it.
Hope this helps.
Pete

How do I stop a date/time comparison from failing when a user is in a different time zone?

I am getting the "LastWriteTime" of my executable and comparing it to an internal DateTime that I have set. If the LastWriteTime is less than or equal to the internal DateTime then I will clear two tables from a database.
This code works great for me in the Pacific Time Zone. But if a user is in another time zone, (example 4 hours ahead of me), then it does not work because the "LastWriteTime" returns the time converted to their time zone. For example, I am looking for the value of "12/12/2012 8:38:12 AM" and if they are 4 hours ahead of me, this value gets automatically changed to "12/12/2012 12:38:12 PM" on their systems.
Can someone please show me what I should modify in my code to take into account for different time zones so the "LastWriteTime" and my 'build2023_EXE_Date' variable both return the same Date/Time so my comparision of the two date/time values don't fail regardless of what time zone my end user is in?
I am using .NET 3.5, not .Net 4.x
//http://stackoverflow.com/questions/1600962/displaying-the-build-date
string w_file = "MyEXE.exe";
string w_directory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
Path.DirectorySeparatorChar + "MyEXE";
DateTime currentExeTime = File.GetLastWriteTime(System.IO.Path.Combine(w_directory, w_file));
DateTime build2023_EXE_Date = new DateTime(2012, 12, 12, 8, 38, 12); //"12/12/2012 8:38:12 AM"
//We need to truncate the millisecond time off of the EXE LastWriteTime
//or else when we compare to our internal DateTime build2323_EXE_Date value,
//it will not match
//http://stackoverflow.com/questions/1004698/how-to-truncate-milliseconds-off-of-a-net-datetime
currentExeTime = new DateTime(
currentExeTime.Ticks - (currentExeTime.Ticks % TimeSpan.TicksPerSecond),
currentExeTime.Kind
);
if (currentExeTime <= build2023_EXE_Date) //If previous build matches or is before the Build 2023 date then clear these two tables.
{
//This will fail the comparision if the user is in a different time zone than me.
//Clear tables
}
Unless you've got a specific need to keep dates in local time or have an associated time zone, I suggest you use universal time instead. This makes working with dates far easier because they all compare sanely, and it can actually be more performant (when you request DateTime.Now, .NET calls DateTime.UtcNow and then performs a relatively expensive adjustment to local time).
Another option is to use DateTimeOffset, which stores a date with an offset (not a time zone! -- for instance, DST will give you different offsets) and makes comparisons as easy as a universal DateTime. Unfortunately, though, GetLastWriteTime doesn't use DateTimeOffset so this might not work for you.
Use the DateTime ToUniversalTime() method

Categories

Resources