I am trying to pass DateTime.MaxValue into a constructor, but for some reason when it is passed, the Ticks property changes from 315537897599999999 to 3155378975990000000, making it difficult to use for comparison.
DateTime dt = DateTime.MaxValue; //here it is 315537897599999999
OfferSetting setting = new OfferSetting(settingCode
, (Equals(row["AccountId"], "")) ? null : row["AccountId"].ToString()
, (Equals(row["Arguments"], "")) ? null : row["Arguments"].ToString()
, (Equals(row["StartDate"], "") || Equals(row["StartDate"], DBNull.Value)) ? DateTime.MinValue : Convert.ToDateTime(row["StartDate"])
, (Equals(row["EndDate"], "") || Equals(row["StartDate"], DBNull.Value)) ? dt : Convert.ToDateTime(row["EndDate"]));
Once in the constructor for OfferSetting, it changes to 3155378975990000000:
public OfferSetting(SettingCode settingCode, string accountId, string arguments, DateTime startDate, DateTime endDate)
: base(MoeState.New)
{
this.Id = "-1";
this.OfferSettingId = "-1";
this.SettingCode = settingCode;
this.AccountId = accountId;
this.Arguments = arguments;
this.StartDate = startDate;
this.EndDate = endDate; //here it is 3155378975990000000
}
Any ideas?
I have a no-repro - I just tried it and can't get it to repro. You will need to debug and if it makes it easy, rewrite the code to assign row["EndDate"] to a variable (even if temporarily) so you can at least see what's in that variable.
FYI, in your second condition, you seem to be testing for row["EndDate"] along with row["StartDate"], which might be contributing to the issue.
(Equals(row["EndDate"], "") || Equals(row["StartDate"], DBNull.Value)) ? dt : Convert.ToDateTime(row["EndDate"]));
As others suggested:
Try Nullable instead of MaxValue. You are likely to run into issues with different time zones and locales without even realizing (esp., e.g. when your code runs on different machines).
Consider using DateTimeOffset instead of DateTime, as it represents 'instantaneous time' instead of 'calendar time'. See here for more discussion. (You'd rather ideally still use Nullable.)
Nullable DateTime struct would be named DateTime? e.g.
DateTime? ndt=null;
You also would need to check if(HasValue()), before poking the actual value field.
if(ndt.HasValue()){/*do what you meant to */}
I figured it out, I am just an idiot, it was passing the wrong value to the constructor.
Simply passing a value through a constructor parameter absolutely cannot change the value, so you can eliminate that part of it.
It's more likely that there is an issue with precision loss. This might happen either when you store the value into the database, or when you're retrieving it.
On the storage side, if you really need to store the full precision of DateTime.MaxValue, then make sure you're using a data type in your database that can support it. For example, if you're using SQL Server, you should use a datetime2 type rather than a datetime type.
On the retrieving side, some of your code appears to be suffering from a common anti-pattern.
Don't do this:
DateTime dt = Convert.ToDateTime(row["yourfield"].ToString());
Instead, do this:
DateTime dt = (DateTime) row["yourfield"];
When you convert to a string and then parse that string, there can be a loss of precision. Also, culture-specific formatting or non-Gregorian calendars can get in the way in certain cases. By simply unboxing it instead, you keep it in the original type. No strings required.
Same goes for other types, including integers, booleans and strings. The underlying database client has already made the best conversion from the native database type to an appropriate .Net type. No need to do that work again.
Related
For reasons beyond my control, I find myself using .net mobile 3.5. I need to be able to use the Rows.Find(Object) function on a DataTable where the Primary Key is a DateTime.
Ex: DataRow temp = exDataSet.exDataTable.Rows.Find(exDateTime);
I have not been able to make the C# DateTime value match that which is stored in the DataTable.
Based on guidance from these forums and from other resources I have tried changing the DataColumn's DateTimeMode, I have tried converting the DateTime to SqlDateTime, and I have tried the (much less desired) .ToString("yyyy-MM-dd HH:mm:ss") function, all to no avail. Also, I am unable to use DateTime2 as far as I am aware.
Any recommendations?
You need to make both Dates in same format before comparison, Just sharing an example as below , you can use same concept in your code.
DateTime dt1;
DateTime dt2;
if (DateTime.TryParse(strDate1, out dt1) && DateTime.TryParse(strDate2, out dt2))
{
if (dt1.Date == dt2.Date)
{
// the dates are identical
}
}
This question already has answers here:
datetime issue with 01/01/1900
(3 answers)
Closed 6 years ago.
I have been working on a backend i.e. in Sql server 2012. I have declare a field as Date in table i.e. ParawiseDate datetime.
And I am passing a NULL to it from C# i.e.
sqlcom.Parameters.AddWithValue("#ParawiseDate", NULL);
Problem:
It saves the dates as 1900-01-01 instead of NULL. I tried "" and also got saved as 1900-01-01.
Why ?
Make sure it allow null values in ParawiseDate column.Also instead of passing Null try DBNull.value
sqlcom.Parameters.AddWithValue("#ParawiseDate", DbNull.Value);
SELECT cast(NULLIF(t.[ParawiseDate],'') AS DATE)
FROM tablename t
I believe for DateTime, you can declare the type with "?" , otherwise they would default to 1900-01-01
DateTime ? Parameter;
Also try passing in
typeof(System.DateTime)
instead of NULL, on the second parameter
It is essential to know what binary representation of data is and what casts are allowed. Without that, any programmer is somewhat blind. Regarding this case, in MS SQL default date value is 1900-01-01. In older CLR AddWithValue with DBNull.Value as a value was equivalent to setting field to default.
I didn't dealt with 4.0 CLR environment, but I may expect that NULL could be casted to DBNull? In any case it is not a date value, or if NULL could be implicitly casted into Date with a default value? (latter would say that MS again steps away from standards, NULL must now be equal to pointer to any object) Most likely an undocumented side-effect.
public SqlParameter AddWithValue(
string parameterName,
object value
)
Parameters
parameterName
Type: System.String
The name of the parameter.
value
Type: System.Object
The value to be added. Use DBNull.Value instead of null, to indicate a null value.
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparametercollection.addwithvalue(v=vs.110).aspx
Date and DateTime cannot be NULL, though field in table can be set to allow null values. Reading no data usually would get result in getting default value, for safety reasons. That requires separate check (isDBNull?)
Only legitimate values for date in SQL (Microsoft flavor at least) are 0001-01-01 through 9999-12-31 , that should be given explicitly, otherwise a default would be used.
I am writing a unit test which stores an object with a DateTime parameter into a DATETIME2 SQL Server database column. I then create a temporary DateTime object called new_date_time and set that value to DateTime.Now.
The new_date_time value is then used to update the previous value and the SQL query to do this completes successfully.
When re-reading the object back from the database I receive the correct datetime values for days/hours/minutes but the .Ticks value is different from the new_date_time variables .Ticks property. The value returned from the read call returns the last 4 digits of the .Ticks property as zeros.
Why is this rounding occurring making my Assert.AreEqual fail?? :)
Thanks
I guess you are using Parameters.AddWithValue when writing the date to Sql Server. From MSDN the inferred type of a CLR DateTime is SqlDbType.DateTime and not SqlDbType.DateTime2 so the precision is being lost when writing your date to the database.
Explicitly setting the type to datetime2 will solve the issue. For example:
command.Parameters.AddWithValue("#now", DateTime.Now).SqlDbType =
SqlDbType.DateTime2;
Edit
#marc_s makes a good point with his comment:
You should read (and embrace!) Can we stop using AddWithValue() already?
To avoid these kind of issues from biting you, you could get into the habit of using the Add method on the parameters collection which takes the SqlDbType in some overloads and then set the Value property on that rather than using the AddWithValue method:
command.Parameters.Add("#now", SqlDbType.DateTime2).Value = DateTime.Now;
Maybe your database field is not storing your entire DateTime.Now value, because it's not precise enough. Why don't you simply compare your dates after you've formatted them as you like?
eg: (untested):
var databaseDate = d1.ToString("MM/dd/yyyy HH:mm:ss.fff");
var tempDate = d2.ToString("MM/dd/yyyy HH:mm:ss.fff");
Assert.AreEqual(databaseDate, tempDate);
I tested: using Linq To Entities My DateTime.Now is correctly saved to my datetime2(7) and equality test return True.
Are you sure you're passing your correct datetime value to the database? without truncating it?
In the web app I'm working on, the web app should be able to accept null DateTimevalues, because customers might be hesitant to give information about their Date of Birth. Of course, this won't be an easy task, because in C#, DateTime is not nullable.
DateTime rawBirthDate = Convert.ToDateTime(txtDOB.Text);
fxTxn.BirthDate = rawBirthDate;
with that, I had to change my code to accept a null value:
DateTime? rawBirthDate = string.IsNullOrEmpty(txtBirthDate) ? (DateTime?)null : DateTime.Parse(txtBirthDate);
fxTxn.BirthDate = Convert.ToDateTime(rawBirthDate);
this code, in turn, returns 1/1/0001 12:00:00.000 AM. However, MSSQL throws a DateOutOfRangeException, saying the date must be between 1/1/1753 and 12/31/9999.
I'm completely stuck in here. On my SQL table, I allowed the BirthDate column to accept null values. Question now is, how do I make C# consider null DateTime values? The end result would be that, if the Customer did not provide Date of Birth information, the system should still be able to save the record but the BirthDate column in the customer's record would still be NULL.
What you need to do is this: your column table should accept null for BirthDate (that's correct). In C#, make the variable rawBirthDate nullable.
Now, the condition you need to check is:
rawBirthDate.HasValue
If it's true, then insert the date in db.
If false, do not insert anything in the db (that's what 'allow null' means in SQL).
how do I make C# consider null DateTime values
Your value was null. The problem is that you converted it to a standard DateTime which is giving you the DateTime.MinValue (1/1/0001)
I think the problem might be in the code that actually inserts the value into database:
...
var valueToInsert = rawBirthDate ?? DBNull.Value;
...
Why are you converting null value in datetime, if you define nullable variable then it can store null vaue. Actually you need to define BirthDate property also nullable and store null value if user have not entered date like
fxTxn.BirthDate = string.IsNullOrEmpty(txtBirthDate) ? null : DateTime.Parse(txtBirthDate);
In db you need to make that column to allow null value and check value of BirthDate like
if (fxTxn.BirthDate.HasValue)
{
// pass value in db otherwise not
}
On this project, I am tracking when something is created, edited, and finally processed. I have three DateTime fields setup for this. The code below is for when I create the record.
newsArchive.CreateDateTime = DateTime.Now;
newsArchive.ModifyDateTime = DateTime.MinValue;
newsArchive.SendDateTime = DateTime.MinValue;
naRepository.Add(newsArchive);
naRepository.Save();
I am getting "SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM." when I try to add it. I know I can't send a NULL. How would you handle this?
I am using Linq2SQL to process this.
Why can't you send a null? AFAIK, Linq2SQL supports nullable value types; you just need the column in the DB to be nullable or L2S won't project the DAO with the nullable type.
You could use (DateTime)(SqlDateTime.MinValue) instead of DateTime.MinValue. This will use the minimum SQL-compatible datetime value, explicitly cast to DateTime.
Though both SqlDateTime and DateTime actually store time as a UInt64 "Ticks" value, the difference between the two types is that SQL Server uses a different epoch (value for zero) and a different resolution (what 1 "tick" represents in fractions of a second) than the CLR's DateTime.
Which version of SQL Server are you using? If you are using SQL 2008 (or 2008 R2) you can use the datetime2 data type which can support the full range of the .NET DateTime type.
Otherwise, use NULL (your model will need to have a property of type Nullable<DateTime>) or live within the limitations of the data type and DateTime.MinValue exceeds the limit of the SQL datetime type.
Create your own minimum date - a Date variable with value 1/1/1753 12:00:00 AM and use that instead of DateTime.MinValue
The datetime2 datatype allows dates as early as year 1. You can also use DateTime? to allow null dates in your .net code