DateTime.MinValue and SqlDateTime overflow - c#

I don't want to validate txtBirthDate so I want to pass DateTime.MinValue in database.
My code:
if (txtBirthDate.Text == string.Empty)
objinfo.BirthDate = DateTime.MinValue;
else
objinfo.BirthDate = DateTime.Parse(txtBirthDate.Text);
DateTime.MinValue return Date = {1/1/0001 12:00:00 AM}
I got a SQL Error:
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
I under stand it but I don't understand why DateTime.MinValue return invalid date time which is unable to insert in database.How to handle this type of situation?

Very simple avoid using DateTime.MinValue use System.Data.SqlTypes.SqlDateTime.MinValue instead.

Basically, don't use DateTime.MinValue to represent a missing value. You can't use DateTime.MinValue in a SQL Server DateTime field, as SQL Server has a minimum value of the start of 1753.
Instead, make your BirthDate property a Nullable<DateTime> (aka DateTime?), and set it to null when you don't have a value. Also make sure your database field is nullable. Then you just need to make sure that that null ends up as a NULL value in the database. Exactly how you do that will depend on your data access, which you haven't told us anything about.

Well... its quite simple to get a SQL min date
DateTime sqlMinDateAsNetDateTime = System.Data.SqlTypes.SqlDateTime.MinValue.Value;

Although it is an old question, another solution is to use datetime2 for the database column.
MSDN Link

Here is what you can do. Though there are lot many ways to achieve it.
DateTime? d = null;
if (txtBirthDate.Text == string.Empty)
objinfo.BirthDate = d;
else
objinfo.BirthDate = DateTime.Parse(txtBirthDate.Text);
Note: This will work only if your database datetime column is Allow Null. Else you can define a standard minimum value for DateTime d.

I am using this function to tryparse
public static bool TryParseSqlDateTime(string someval, DateTimeFormatInfo dateTimeFormats, out DateTime tryDate)
{
bool valid = false;
tryDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
System.Data.SqlTypes.SqlDateTime sdt;
if (DateTime.TryParse(someval, dateTimeFormats, DateTimeStyles.None, out tryDate))
{
try
{
sdt = new System.Data.SqlTypes.SqlDateTime(tryDate);
valid = true;
}
catch (System.Data.SqlTypes.SqlTypeException ex)
{
}
}
return valid;
}

From MSDN:
Date and time data from January 1, 1753, to December 31, 9999, with an
accuracy of one three-hundredth second, or 3.33 milliseconds. Values
are rounded to increments of .000, .003, or .007 milliseconds. Stored
as two 4-byte integers. The first 4 bytes store the number of days
before or after the base date, January 1, 1900. The base date is the
system's reference date. Values for datetime earlier than January 1,
1753, are not permitted. The other 4 bytes store the time of day
represented as the number of milliseconds after midnight. Seconds have
a valid range of 0–59.
SQL uses a different system than C# for DateTime values.
You can use your MinValue as a sentinel value - and if it is MinValue - pass null into your object (and store the date as nullable in the DB).
if(date == dateTime.Minvalue)
objinfo.BirthDate = null;

Simply put, don't use DateTime.MinVaue as a default value.
There are a couple of different MinValues out there, depending which environment you are in.
I once had a project, where I was implementing a Windows CE project, I was using the Framework's DateTime.MinValue (year 0001), the database MinValue (1753) and a UI control DateTimePicker (i think it was 1970). So there were at least 3 different MinValues that were leading to strange behavior and unexpected results. (And I believe that there was even a fourth (!) version, I just do not recall where it came from.).
Use a nullable database field and change your value into a Nullable<DateTime> instead. Where there is no valid value in your code, there should not be a value in the database as well. :-)

If you use DATETIME2 you may find you have to pass the parameter in specifically as DATETIME2, otherwise it may helpfully convert it to DATETIME and have the same issue.
command.Parameters.Add("#FirstRegistration",SqlDbType.DateTime2).Value = installation.FirstRegistration;

use extensions
public static class DateTimeExtensions
{
public static DateTime MinValue(this DateTime sqlDateTime)
{
return new DateTime(1900, 01, 01, 00, 00, 00);
}
}
DateTime date = DateTime.Now;
Console.WriteLine("Minvalue is {0} ", date.MinValue().ToShortDateString());

Related

Detect the date format C#

I have some automated C# windows services to upload text to the database. The 'text' is generated by a third party application where we don't have any control.
My issue is that the text contains a column for date.
The default date format is DD/MM/YY. But some times we get MM/YY/DD
Is there any tricky way to identify or convert MM/YY/DD to DD/MM/YY. The data might only contain date for three, four days. So I plan to check if the date is in tolerance with three or four days, it will be accepted. Other wise manually correct it.
For example,
14/08/17 is accepted
08/17/14 is not accepted. Logic should convert this to 14/08/17
Any ideas ?
You could try and parse with the good format, if it goes ok there is no problem, it will return the date. If it goes wrong, you tryparse with the 'secondary format'. If everything goes ok, it will return the date.
Note that if the parsed date it's more than 3 days ahead, it won't count as a valid date and will return null.
if(DateTime.TryParseExact(input, "dd/MM/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateValue)
{
int daysBetween = (dateValue-DateTime.Now).Days
if(daysBetween < 4)
{
return dateValue
}
}
if(DateTime.TryParseExact(input, "MM/yy/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateValue)
{
int daysBetween = (dateValue-DateTime.Now).Days
if(daysBetween < 4)
{
return dateValue;
}
}
return null
If null gets returned, you'll have an invalid date, if not, that will be the parsed date

How to merge two nullable DateTime objects one contaning time other date I need into one object?

I've got two DateTime objects. The FetchTime contains time hh:mm:ss I am insterested in, FetchDate contains date: year, month, day.
Example:
Debug.WriteLine("Time " + FetchTime);
Debug.WriteLine("Date " + FetchDate);
displays for example:
Time 2014-09-10 23:04:00
Date 2014-09-15 00:00:00
and I would like to get DateTime object which looks like that:
2014-09-15 23:04:00
I would like to merge those two into one or modify one of them. I thought it would be easy but I can't see almost any methods for DateTime object. Is it achievable or first I must convert DateTime to another type then convert it back? Finally, I have to have DateTime object because it is going to be added to SQL database .
EDIT:
I refer to nullable DateTime: DateTime? FetchDate, DateTime? FetchTime.
Just use the DateTime constructor
var date = new DateTime(FetchDate.Year, FetchDate.Month, FetchDate.Day,
FetchTime.Hour, FetchTime.Minute, FetchTime.Second);
Update: It seems like you are using nullable DateTime. So you should get the underlying DateTime value using Value property.
var fetchDate = FetchDate.Value;
var fetchTime = FetchTime.Value;
var date = new DateTime(fetchDate.Year, fetchDate.Month, fetchDate.Day,
fetchTime.Hour, fetchTime.Minute, fetchTime.Second);
Whenever you use the ? suffix on a value type you will always need to call the .Value member before you can call any members on your type.
The ? suffix is actually a special symbol for the compiler to transform your type reference from T? to Nullable<T>. For additional details see the MSDN documentation for Nullable`1.
For your example you will want to use the following to merge the values together.
new DateTime(
FetchDate.Value.Year,
FetchDate.Value.Month,
FetchDate.Value.Day,
FetchTime.Value.Hour,
FetchTime.Value.Minutes,
FetchTime.Value.Seconds)
Make sure to check for null using == null or .HasValue if you are concerned about null values, otherwise you will encounter a System.InvalidOperationException.
For fun, here is another possible way:
DateTime date = new DateTime(2014, 9, 15);
DateTime datetime = new DateTime(2014, 9, 10, 23, 4, 0);
DateTime combined = date + datetime.TimeOfDay;

Convert Timeformat to normal datetime

I have to convert this time format string (20130221191038.576375+330) to normal datetime through c# classes like datetime.
please share the idea to convert this..
Thanks guys, I got the solution for my requirement with the help of Erik,tung and BlackHatShadow.
Referred this
this also
The format you have is a CIM_DATETIME value, which is almost simple to parse. The only problem is that it specifies the timezone as an offset in number of minutes.
You can use the DateTime.TryParseExact to convert the portion of the string prior to the timezone specifier, then subtract the timezone value (in minutes) from the result to get the UTC datetime. Then you can convert to local time if you need, or leave it in UTC form.
public static DateTime? CIMToUTCDateTime(string CIM_DATETIME)
{
// CIM_DATETIME must be 25 characters in length
if (string.IsNullOrEmpty(CIM_DATETIME) || CIM_DATETIME.Length != 25)
return null;
// Get the datetime portion of the string without timezone offset
string dtPortion = CIM_DATETIME.Substring(0, 21);
// convert to datetime
DateTime dt;
if (!DateTime.TryParseExact(dtPortion, "yyyyMMddHHmmss.ffffff", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AssumeUniversal | System.Globalization.DateTimeStyles.AdjustToUniversal, out dt))
return null;
// subtract timezone offset to get UTC time equivalent
int tzoffset;
if (!Int32.TryParse(CIM_DATETIME.Substring(21), out tzoffset))
return null;
dt = dt.AddMinutes(-tzoffset);
// return UTC datetime
return dt;
}
And now that I've written this horrid little method, you've gone and found another solution. Typical :P
I know you already found a solution, but I came across this nice ManagementDateTimeConverter .Net class that does exactly what you want. All you need to do is:
// This gets converted to your local time
DateTime converted = ManagementDateTimeConverter.ToDateTime("20130221191038.576375+330")
// If you want the UTC equivalent:
converted.ToUniversalTime()

compare between dates in .net

I want to compare between two dates.
From both the dates, I am fetching only date component using ToShortDateString(), as shown below. Now the problem is when I'm comparing the two dates. Its throwing error --
"Operator >= can't be applied to operands of type string and string."
DateTime srtdate = Convert.ToDateTime(allitem["StartDate"].Text.ToString());
DateTime srtdate = Convert.ToDateTime(allitem["StartDate"].Text.ToString());
(DateTime.Now.ToShortDateString() >= srtdate.ToShortDateString())
I need to compare date component only, NOT date and time together.
Please suggest what is the alternative way. Thanks
To JON:-
(I went tyhrough all what you explained and understood hopefully what the point actually you trying to make. Just to clarify more and make a last check I ll show an example.)
I have an web interface, where I give a start date and end date for a XYZ name (Note I can enter only date here, not time).
Start Date - 22-Feb-2012 AND End Date - 22-Feb-2012
Now in back end (code), if Start date and End date is same as Current date OR current date is in between start and end date, I want a ACTIVE flag set or else not. I give the condition as this:-
if ((DateTime.Today >= strdate.Date) && (DateTime.Today <= enddate.Date))
lblCondition.Text = "CHECKED";
Now when I debug the code,
Both DateTime.Today and strdate.Date gives the value as 2/22/2012 12:00:00 AM.
So, Jon my question is:- Would 'today' and 'date' work as per mentioned requirement, where only date component used. I hope it would.
Thanks a lot for all your explanantion before.
Why are you converting to a string representation at all? If you only want to compare the date parts to two DateTime values, just use the Date property on each of them:
if (x.Date >= y.Date)
And the Today property is equivalent to DateTime.Now.Date.
Both Date and Today strip off the time part, leaving a time of midnight. It's not ideal that you've still got a type which is capable of representing times, but that's just the way the DateTime API works :(
Note that you should usually avoid using DateTime.Now or DateTime.Today in web applications unless you're really comfortable with it using the system default time zone as the day boundary. The user's idea of "today" may not be the same as the server's.
You should avoid using string conversions unless your goal is really to get a text representation.
Of course another alternative would be to use the date/time library I'm building, Noda Time, where you could use a LocalDate type - obviously that makes it clearer that you're only interested in the date and not the time.
EDIT: As the OP seems unconvinced that Date really does ignore the time component, here's an example:
using System;
public class Test
{
static void Main()
{
// Two DateTime values with different times but
// on the same date
DateTime early = new DateTime(2012, 2, 22, 6, 0, 0);
DateTime late = new DateTime(2012, 2, 22, 18, 0, 0);
Console.WriteLine(early == late); // False
Console.WriteLine(early.Date == late.Date); // True
}
}
DateTime.Today >= strdate.Date
some thoughts
Think at the the following example: you need to compare the following numbers 1.5 and 2.5. These are represented in .Net as decimal, double or float, but let's use decimal. The greater one is 2.5
Let's say you need to compare the integral part of these numbers (1. and 2.). You will still use the decimal type to do the comparison.
Math.Truncate(x) ? Math.Truncate(y) // x = 1.5, y = 2.5
Same as for the DateTime. DateTime.Date will return the "integral" part of your date as Math.Truncate returns the integral part of a "real" number, but both will base on their original type.
hope this helps you.
using System;
public class Example
{
public static void Main()
{
DateTime date1 = new DateTime(2009, 8, 1, 0, 0, 0);
DateTime date2 = new DateTime(2009, 8, 1, 12, 0, 0);
int result = DateTime.Compare(date1, date2);
string relationship;
if (result < 0)
relationship = "is earlier than";
else if (result == 0)
relationship = "is the same time as";
else
relationship = "is later than";
Console.WriteLine("{0} {1} {2}", date1, relationship, date2);
}
}
// The example displays the following output:
// 8/1/2009 12:00:00 AM is earlier than 8/1/2009 12:00:00 PM

DateTime.Now - first and last minutes of the day

Is there any easy way to get a DateTime's "TimeMin" and "TimeMax"?
TimeMin: The very first moment of the day. There is no DateTime that occurs before this one and still occurs on the same day.
TimeMax: The very last moment of the day. There is no DateTime that occurs after this one and still occurs on the same day.
These values would be helpful for filtering and doing date-related queries.
Here are two extensions I use to do exactly that.
/// <summary>
/// Gets the 12:00:00 instance of a DateTime
/// </summary>
public static DateTime AbsoluteStart(this DateTime dateTime)
{
return dateTime.Date;
}
/// <summary>
/// Gets the 11:59:59 instance of a DateTime
/// </summary>
public static DateTime AbsoluteEnd(this DateTime dateTime)
{
return AbsoluteStart(dateTime).AddDays(1).AddTicks(-1);
}
This allows you to write:
DateTime.Now.AbsoluteEnd() || DateTime.Now.AbsoluteStart()
or
DateTime partyTime = new DateTime(1999, 12, 31);
Console.WriteLine("Start := " + partyTime.AbsoluteStart().ToString());
Console.WriteLine("End := " + partyTime.AbsoluteEnd().ToString());
I'd use the following:
DateTime now = DateTime.Now;
DateTime startOfDay = now.Date;
DateTime endOfDay = startOfDay.AddDays(1);
and use < endOfDay instead of <= endOfDay. This will mean that it will work regardless of whether the precision is minutes, seconds, milliseconds, ticks, or something else. This will prevent bugs like the one we had on StackOverflow (though the advice was ignored).
Note that it is important to only call DateTime.Now once if you want the start and end of the same day.
try
//midnight this morning
DateTime timeMin = DateTime.Now.Date;
//one tick before midnight tonight
DateTime timeMax = DateTime.Now.Date.AddDays(1).AddTicks(-1)
If you are using this for filtering, as your comments suggest, it is probably a good idea to save DateTime.Now into a variable, just in case the date ticks over between the two calls. Very unlikely but call it enough times and it will inevitably happen one day (night rather).
DateTime currentDateTime = DateTime.Now;
DateTime timeMin = currentDateTime.Date;
DateTime timeMax = currentDateTime.Date.AddDays(1).AddTicks(-1)
One small tweak to hunter's solution above...
I use the following extension method to get the end of the day:
public static DateTime EndOfDay(this DateTime input) {
return input.Date == DateTime.MinValue.Date ? input.Date.AddDays(1).AddTicks(-1) : input.Date.AddTicks(-1).AddDays(1);
}
This should handle cases where the DateTime is either DateTime.MinValue or DateTime.MaxValue. If you call AddDays(1) on DateTime.MaxValue, you will get an exception. Similarly, calling AddTicks(-1) on DateTime.MinValue will also throw an exception.
You must be careful to use
(new DateTime()).AddDays(1).AddTicks(-1);
when it is passed to stored procedure.
It could happen that the value will be approximated to next day.
Like other answerers, I'm not quite sure what you're asking for, but incase you want the smallest possible time and the largest possible time, (not just in a day), then there's DateTime.MinValue and DateTime.MaxValue which return 1/1/0001 12:00:00 AM
and 12/31/9999 11:59:59 PM respectively.
I would advise that you look at this answer:
How can I specify the latest time of day with DateTime
If your original DateTimes also potentially include times, using the AddDays() method will add a full 24 hours, which may not be precisely what you want.
public static DateTime ToEndOfDay(this DateTime time)
{
var endOfDaySpan = TimeSpan.FromDays(1).Subtract(TimeSpan.FromMilliseconds(1));
return time.Date.Add(endOfDaySpan);
}
Please note that if you're passing this time to sql server you should use
dateTime.Date.AddDays(1).AddMilliseconds(-3);
See:
How do I get the last possible time of a particular day
DateTime.Today.AddDays(1).AddSeconds(-1);
Not very exact, but fixed my problems. Now we can use AddMilliseconds, AddTicks and etc. I think it will just vary on what would satisfy your need.

Categories