This question already has answers here:
How to find time differences between two time in c#
(4 answers)
Closed 8 years ago.
For example, how do I find the time difference between (01/23/2015 10:10 am and 01/24/2015 06:00 am), or between (01/23/2015 10:10 pm and 01/24/2015 06:00 am), or between (01/24/2015 05:10 am and 01/24/2015 06:00 am).
The main purpose: I have a scheduled task method that runs exactly at 6:00 am and the scheduled task is written in global.aspx. I want to find the correct time difference between the time I start the application and 6:00 am. Based on that time difference, I can keep the thread on sleep until that time, and then run the method.
From the solutions provided if we subtract higher from lower value(10-6) it give a positive result. but if lower is subtracted from higher value (6-10) it give me a negative result. which i can't use as a value to be provided in this particular case: System.Threading.Thread.Sleep(TimeSpan.FromHours(result)).
Please help me out in providing the logic to handle all the
three scenarios mentioned and give a positive result value.
DateTime gives Compare method, which can be used.
DateTime.Compare(d1,d2) returns an integer. If return value is less than 0, then d1 < d2, d1=d2 if return value is 0 and d1>d2 if return value >0.
If you have DateTime and/or Timespan types, you should be able to use the subtraction operator.
The difference of 2 DateTime Values is a Timespan:
DateTime dt1 = GetSomeValue() ;
DateTime dt2 = GetAnotherValue() ;
Timespan delta = dt1 - dt2 ;
The difference of a DateTime and a Timespan is a DateTime:
DateTime dt = GetSomeValue() ;
Timespan ts = GetAnotherValue() ;
DateTime delta = dt - ts ;
The difference of two Timespan Instances is a Timespan:
Timespan ts1 = GetSomeValue() ;
Timespan ts2 = GetAnotherValue() ;
Timespan delta = ts1 - ts2 ;
Any the combo is invalid.
In general, one can subtract one DateTime value from another, which will return a TimeSpan value representing the difference between the two. But it is not clear from your question what the context is and whether you already have DateTime values in the first place.
If not, you can initialize your DateTime values in a variety of ways. For example, if you actually have strings like what you wrote in your question, you could do something like this:
string startTimeText = "01/23/2015 10:10 am", endTimeText = "01/24/2015 06:00 am";
DateTime startTime, endTime;
startTime = DateTime.Parse(startTimeText, null, DateTimeStyles.AssumeUniversal);
endTime = DateTime.Parse(endTimeText, null, DateTimeStyles.AssumeUniversal);
TimeSpan timeDifference = endTime - startTime;
A couple of notes:
I passed AssumeUniversal to the Parse() method. You need to be very careful about doing these kinds of calculations. Preferably, all your times are in UTC already, or can be converted before you have to do the calculation. Otherwise, if the time zone is one that uses Daylight Saving Time (i.e. most of the time zones in the world), you can get errors when dealing with times that span the switch-over from or to DST.
The - operator is overloaded for DateTime, allowing you to write the expression to calculate the difference in a more readable way. Similar operator overloads exist for other common date/time computations.
Related
I have two time values one is stored in xml file
<bicycle>
<Id>3002</Id>
<TimeSpan>5/23/2020 7:11:02 AM</TimeSpan>
<CurrentLocation>0</CurrentLocation>
<UserId>1521217035</UserId>
</bicycle>
Calling this value from code
node.SelectSingleNode("TimeSpan").InnerText = DateTime.Now.ToString();
other time value is system current time How can i compare these two and get difference?
TimeSpan span = date2 - date1;
double seconds = span.TotalSeconds;
https://learn.microsoft.com/en-us/dotnet/api/system.timespan?view=netcore-3.1
For more info.
Also date2 and date1 are DateTime types. Convert your string using Convert.ToDateTime or DateTime.ParseExact
I'm assuming I should just parse the string into a DateTime and go from there... But is there a better way of doing this?
You can use the DateTimeOffset struct, which has a ToUnixTimeSeconds (or ToUnixTimeMilliseconds) method you can use:
long unixTimestamp = DateTimeOffset.Parse("2018-12-27T02:23:29").ToUnixTimeSeconds();
If you're curious how it's done, the source is here: https://referencesource.microsoft.com/#mscorlib/system/datetimeoffset.cs,8e1e87bf153c720e
You should parse it to a normal DateTime object using something from the DateTime.Parse/ParseExact family of functions, and then call a method like this:
public int ToUnixTime(DateTime d)
{
var epoch = new DateTime(1970,1,1);
return (int)(d - epoch).TotalSeconds;
}
DateTime interally stores the "Ticks" (a invented Time unit) since "12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001), in the Gregorian calendar". As a Int64/Long Number. DateTime thus beats UnixTime easily in possible values. Converting to DateTime should be lossless.
Any ToString() call, any other Property call will simply calculate the values based on those Ticks (and culture/Timezone settings for ToString()). Everything else is just a interpretation of the Tick value.
You should parse to DateTime. And getting from Ticks to something as inprecise as the UnixTime is easy math. See Joels Answer for that.
Do note however the DateTimes preccision and accuaracy do not match fully: https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-datetime/ DateTime.Now will usually give you only return values in 18 ms steps. And even the Stopwatch has issues with values < 1 ms.
I need to store a DateTime value which is sent to the Database from a C# application which is using DateTime.UtcNow. If I save it to the DateTime column, the milliseconds value are always 000. But while debugging from the application, the milliseconds value is sent from the application to the database.
What am I missing?
It might happen because datetime column rounds milliseconds part. From documentation;
Accuracy
Rounded to increments of .000, .003, or .007 seconds
Since you didn't show us how often you store your UtcNow value (I assume you store it as a DateTime, not it's string representation because parameterless ToString and other standard formats does not generates millisecond part usually), this may happen but if you do it in short time intervals, it would be really weird always rounding to 000 as milliseconds part. But of course, we can't know that, yet.
On the other hand, datetime2 type does not do any rounding. And it's accuracy is 100 nanoseconds.
Accuracy
100 nanoseconds
Here's no pleasant way to use Datetime because
SQL Server only stores time to approximately 1/300th of a second.
These always fall on the 0, 3 and 7 milliseconds
SQL Server 2008 has much more precision available. The datetime2 datatype will accurately store values like this: 2008-12-19 09:31:38.5670514
See reference documentation
It looks to me like something/someone is doing a default-ToString instead of using ToString with the proper ISO-standard format.
Proper ISO-format for date with time is
yyyy-MM-ddTHH:mm:ss.fff
while date-only ISO-format is
yyyyMMdd
You can check:
static void Main(string[] args)
{
System.DateTime cur = System.DateTime.UtcNow;
string strDefault = cur.ToString();
string str = cur.ToString("yyyy-MM-ddTHH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture);
System.Console.WriteLine(str);
System.Console.WriteLine(strDefault);
}
This outputs
2016-03-03T08:31:27.324
03.03.2016 08:31:27
You might also want to use the HEX-format, as this enhances precision, or at least preserves a value that already was in SQL-Server. If you don't use hex-representation, you can get a 23:59:59.997 value from SQL-server and resave, and you'll have 00:00:00 with day+1. Using the hex-format preserves .997, while saving an ISO-string will yield day+1.
public static string GetTimeAsHex(System.DateTime dt)
{
System.DateTime zero = new System.DateTime(1900, 1, 1);
System.TimeSpan ts = dt - zero;
System.TimeSpan ms = ts.Subtract(new System.TimeSpan(ts.Days, 0, 0, 0));
double x = System.Math.Floor(ms.TotalMilliseconds / 3.3333333333);
string hex = "0x" + ts.Days.ToString("X8") + System.Convert.ToInt32(x).ToString("X8");
return hex;
}
Anyway, as others have already told you, SQL-server datetime is only precise to within a 4 ms error margin. This is why you should use datetime2, as it fixes many issues (bugs/"features") in datetime, including insufficient precision in the milliseconds range.
If you are building your INSERT statement as a string, try specifying the output of milliseconds in the string conversion
DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
This was born from my previous question
I have a DateTime in c#.
Then this value is inserted to database.
After that select this value and compare that date is the same as it was in the beginning.
What is the best way to do this?
Since SQL datetime has different ticks, DateTime from the first step will not be the same as SQL DateTime (row["MyDate"])
How to compare them?
Subtract one from the other & check the ticks of the resulting TimeSpan to be within acceptable limits for the difference in tick length
You can use the SqlDateTime structure.
DateTime now = DateTime.Now;
SqlDateTime sqlNow = new SqlDateTime(now);
bool equal = now == sqlNow.Value; // false
So if you have a DateTime and want to know if it's equal to a DB-DateTime use:
Assert.Equal(dbEndTime, new SqlDateTime(endTime).Value); // true
SqlDateTime:
Represents the date and time data ranging in value from January 1,
1753 to December 31, 9999 to an accuracy of 3.33 milliseconds to be
stored in or retrieved from a database. The SqlDateTime structure has
a different underlying data structure from its corresponding .NET
Framework type, DateTime, which can represent any time between
12:00:00 AM 1/1/0001 and 11:59:59 PM 12/31/9999, to the accuracy of
100 nanoseconds. SqlDateTime actually stores the relative difference
to 00:00:00 AM 1/1/1900. Therefore, a conversion from "00:00:00 AM
1/1/1900" to an integer will return 0.
if you ignore millisecond difference than you can try this
Select * from MyTable DATEADD(ms, -DATEPART(ms, endTime), endTime) = #value
I want to store dates as numbers in a table. I know how to do that but I don't know how to go back. How can I cast a long variable to ToDateTime.
DateTime now = DateTime.Now;
long t = now.ToFileTime();
DateTime today = t.ToDateTime; // I am looking for something like this line. This Method does not exist
I know there are many ways of converting DateTime to long. I don't mind which technique to use. I just want to have a way where I can convert back and forth.
To long from DateTime:
long DateTime.Ticks
To DateTime from long:
new DateTime(long)
From long to DateTime: new DateTime(long ticks)
From DateTime to long: DateTime.Ticks
use the pair long t = now.Ticks and DateTime Today = new DateTime(t)
Since you're using ToFileTime, you'll want to use FromFileTime to go the other way. But note:
Ordinarily, the FromFileTime method
restores a DateTime value that was
saved by the ToFileTime method.
However, the two values may differ
under the following conditions:
If the serialization and deserialization of the DateTime value occur in different time zones. For
example, if a DateTime value with a
time of 12:30 P.M. in the U.S. Eastern
Time zone is serialized, and then
deserialized in the U.S. Pacific Time
zone, the original value of 12:30 P.M.
is adjusted to 9:30 A.M. to reflect
the difference between the two time
zones.
If the DateTime value that is serialized represents an invalid time
in the local time zone. In this case,
the ToFileTime method adjusts the
restored DateTime value so that it
represents a valid time in the local
time zone.
If you don't care which long representation of a DateTime is stored, you can use Ticks as others have suggested (Ticks is probably preferable, depending on your requirements, since the value returned by ToFileTime seems to be in the context of the Windows filesystem API).
There are several possibilities (note that the those long values aren't the same as the Unix epoch.
For your example (to reverse ToFileTime()) just use DateTime.FromFileTime(t).
There is a DateTime constructor that takes a long.
DateTime today = new DateTime(t); // where t represents long format of dateTime
long dateTime = DateTime.Now.Ticks;
Console.WriteLine(dateTime);
Console.WriteLine(new DateTime(dateTime));
Console.ReadKey();
If you want to use seconds since 1970 instead of Ticks:
UTC:
long secondsSince1970 = DateTimeOffset.Now.ToUnixTimeSeconds();
Local time:
long secondsSince1970 = DateTime.Now.Ticks / 10000000 - 62135596800;
And back to DateTime
DateTime value = DateTime.MinValue.AddSeconds(secondsSince1970).AddYears(1969);
I will add some additional conversion from string to DateTime to long
string timeString = "2016-08-04";
DateTime date = DateTime.Parse(timeString);
long dateTime = date.Ticks;
And here is the shorthand sort of speak:
long dateTime = DateTime.Parse("2016-08-04").Ticks;
//And for the long to DateTime
DateTime date = new DateTime(dateTime);