How to compare sql datetime and c# datetime - c#

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

Related

Comparing DateTime with SqlDateTime.MinValue

When I compare a DateTime variable with SqlDateTime.MinValue:
if (StartDate > SqlDateTime.MinValue)
{
// some code
}
I get the following runtime exception if StartDate is < SqlDateTime.MinValue:
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and
12/31/9999 11:59:59 PM.
This can be easy solved with a small change:
if (StartDate > SqlDateTime.MinValue.Value)
{
// some code
}
I understand that in the first code snippet I'm comparing apples to oranges. What I don't understand is the exception message. It seems like I'm assigning a DateTime value to a SqlDateTime variable.
What am I missing?
The .NET native DateTime type (to be specific, its a structure) holds a broader range of possible values than the SqlDateTime data type can support. More specifically, a DateTime value can range from 01/01/0000 to a theoretical 12/31/9999.
When the compiler tries to coerce the types for comparison, it attempts to put a DateTime value (MinValue.Value) that's outside (below or 'before' in context) the range supported by SqlDateTime - hence the overflow.
From SqlDateTime Structure on MSDN:
SqlDateTime structure
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.

How to remove time in date time?

How to remove a time in date time ? on column date its only display format
I store the value on repository combobox dropdown, and it store the value including the time. How do I remove the time?
I know there's so many question about this. But the solution was by converting it into a date.tostring("dd MMM yyyy"). Is there a solution beside convert it into string? I want the value was date time not a conversion of string.
The code I am using still giving me a time.
DateTime date = Convert.ToDateTime(gridView1.GetDataRow(i)["date"]);
You just forgot to specify the date at the end of the conversion
DateTime date = Convert.ToDateTime(gridView1.GetDataRow(i)["date"]).Date;
DateTime as the name implify, stores date and time.
You cannot remove time part from date because time is an integral part of date.
To understand this you will have to understand how the date and time are stored. Internally, the date and time is stored as a rational number (in fractions). In computer system 24 hours are considered as numeric 1, so when your value is increased by 1 that means your date is increased by 1 day. If the value is increased by 0.5 that means your date is increased by 12 hours (half day).
So, when you have value 42613.00 that means 31st August at midnight (just when the day started) and if you have value 42613.25 that means 6 AM of 31 Aug 2016 and 42613.50 means 12 noon of 31 Aug 2016 (and 42613.39236 means 9:25:00 AM of 31 Aug 2016)
The smallest fraction of time that need to be stored is 1 millisecond. That means the values of DateTime field should have a precision of more than 0.0000000115740740740741. But this is an irrational value (in binary) and hence cannot be stored as such (the nearest match is 1.00000000000000000000000000110001101101011101010000111010111111..., ... means there are more), so I can say that milliseconds are to their nearest approximation values.
.
That said,
if you wish to take only Date part, you can create your own class or struct to store date part of the DateTime and then override operators for date arithematic and provide implicit conversions to convert them to DateTime if any code that expect DateTime field.

Milliseconds value are not getting saved in SQL Server DateTime column

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);

How to find the difference between two time intervals [duplicate]

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.

SQLite Date and Time Datatype

I am trying to build a nice, small database to run on a mobile application (Windows Mobile 5, if you are curious).
In the SQLite Documentation, the Date and Time Datatype is defined as follows:
1.2 Date and Time Datatype
SQLite does not have a storage class set aside for storing dates
and/or times. Instead, the built-in Date And Time Functions of SQLite
are capable of storing dates and times as TEXT, REAL, or INTEGER
values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic
Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these
formats and freely convert between formats using the built-in date and
time functions.
So, saving my DateTime value as either a REAL (float) or INTEGER is the same size.
What about the TEXT format? There are 23 characters above in the text YYYY-MM-DD HH:MM:SS.SSS. Is that 8-bytes per character? If so, that is a HUGE waste of space to store in Text format (which is what I am currently doing).
What about the REAL format? Would I define a base date of November 24, 4714 B.C.? (I am not even sure if Visual Studio 2008 will let me do that. I've never tried.) Then get the TimeSpan between base date and date I want, extract the number of days, and store that?
// is this how to declare this date?
private static readonly DateTime nov24_4714bc = new DateTime(-4714, 11, 24);
public static double GetRealDate(DateTime dateTime) {
// FYI: subtracting dates in .NET returns a time span object
return (dateTime - nov24_4714bc).TotalDays;
}
What about the INTEGER format? Would I define a base date of 1970-01-01 00:00:00 UTC (please tell me how to do that!), then get the TimeSpan between base date and my input date, extract the number of seconds, and store that?
// is this a UTC date?
private static readonly DateTime utc1970_01_01 = new DateTime(1970, 1, 1);
public static double GetIntDate(DateTime dateTime) {
// FYI: subtracting dates in .NET returns a time span object
return (dateTime - nov24_4714bc).TotalSeconds;
}
Any help with this? I am a little confused on a few points.
Use the TEXT format if "human-readability" is important.
Use one of the numeric formats if saving space is important.
If you don't need millisecond precision, you can save space in the TEXT format by only including the part you do need. There are 3 shorter formats accepted by SQLite date/time functions:
YYYY-MM-DD HH:MM:SS (19 characters)
YYYY-MM-DD HH:MM (16 characters)
YYYY-MM-DD (10 characters)
(NEVER use MM/DD/YYYY; it's not supported, and it doesn't sort correctly.)
Would I define a base date of November 24, 4714 B.C.? (I am not even
sure if Visual Studio 2008 will let me do that. I've never tried.)
You can't: System.DateTime only supports the years 1 to 9999. You need to pick a different base date, and then do (dateTime - baseDate).TotalDays + baseDateJD, where baseDateJD is the Julian date of the base date. Some reasonable choices are:
0001-01-01 = JD 1721425.5
1970-01-01 = JD 2440587.5
2000-01-01 = JD 2451544.5

Categories

Resources