I'm trying to subtract short? Days from DateTime? InitialDate to get DateTime FinalDate.
I'm not sure if, because they are nullable objects, this is causing problems with the comparison. I've tried casting days to a TimeSpan without success.
short? Days = 7;
DateTime? InitialDate = new DateTime(2012, 10, 5);
DateTime FinalDate = InitialDate - Days ;
//FinalDate should be 5/3/2012 12:00 AM
FinalDate should be 5/3/2012 12:00 AM.
Since both the variables you are dealing with are nullable types, you have to make use of the .Value property of them to access its value. You can also make use of the .HasValue property to check whether it is having any value.
Now comes the subtraction part, I'm not sure what is the role of TimeSpan that you mentioned in the question. But from the output specified and the name of the variable, I assumed that its the number of days. If my understandings are correct, then you can try the following code to subtract the Days from InitialDate to get the FinalDate
For a safe side, you can check whether the InitialDate has a value or not before accessing them.
DateTime? FinalDate = InitialDate.HasValue ? InitialDate.Value.AddDays(-(Days.HasValue? Days.Value : 0)) : null;
This Example may help you to understand things more clear.
You can just subtract the Days value from the InitialDate using the AddDays method, passing in the negative value of Days. Since you don't show what you want to happen it either value is null I've made FinalDate nullable:
short? Days = 7;
DateTime? InitialDate = 5/10/2012 12:00 AM;
DateTime FinalDate? = null;
if(Days.HasValue && InitialDate.HasValue)
{
FinalDate = InitialDate.Value.AddDays(-Days.Value)
}
Related
I have 2 datetime objects that I need to combine.
This contains the correct date, but the time part is not needed.
DateTime? sessionDate = fl.EventDateTimeStart
This contains the correct time, but the date part needs to be the date value from the
sessionDate object above.
DateTime? sessionStartTime = g.GameStartTime.Value
I tried using some of the various DateTime toString() methods, but found out that
because they are part of a class, they need to remain DateTime? types
so I can't just convert them to a string.
So I came up with this really ugly method:
sessionStartTime = new DateTime(
fl.EventDateTimeStart.Value.Year,
fl.EventDateTimeStart.Value.Month,
fl.EventDateTimeStart.Value.Day,
g.GameStartTime.Value.Hour,
g.GameStartTime.Value.Minute,
g.GameStartTime.Value.Second)
Is there a more elegant way of to do this?
Thanks!
Sure.
var result = fl.Value.Date + g.Value.TimeOfDay;
DateTime.Date returns a DateTime with the time part set to midnight. DateTime.TimeOfDay gets a TimeSpan containing the fraction of the day that has elapsed since midnight.
Make sure that both of your DateTimes have the same Kind, otherwise the result might not be what you expect.
DateTime? arrival = (DateTime?)(t.ArrivalDate.Value);
DateTime? departure = (DateTime?)(t.DepartureDate);
Okay i know both of them are nullable and .TotalDays does not work on nullable object. So kindly tell me how am i supposed to find days difference between these two objects.
Note:
Both objects contains Date(s) i.e. are not null
Since there's no meaningful value to their difference if any of them is null, you only need to concern yourself with the case where they're not:
DateTime? arrival = (DateTime?)(t.ArrivalDate.Value);
DateTime? departure = (DateTime?)(t.DepartureDate);
double? totalDays = arrival.HasValue && departure.HasValue
? (double?)(departure - arrival).GetValueOrDefault().TotalDays
: null;
The subtraction should work because of implicit casting to DateTime.
Note: Both objects contains Date(s) i.e. are not null
If you are sure that dates never have null then you can use .Value for nullable DateTime objects. You will get exception when any of them is null.
double days = departure.Value.Subtract(arrival.Value).TotalDays;
//Set dates
DateTime? beginDate = DateTime.Now;
DateTime? endDate = DateTime.Now.AddDays(10);
//Check both values have a value (they will based on above)
//If they do get the ticks between them
long diff = 0;
if (beginDate.HasValue && endDate.HasValue)
diff = endDate.Value.Ticks - beginDate.Value.Ticks;
//Get difference in ticks as a time span to get days between.
int daysDifference = new TimeSpan(diff).Days;
Here i give you tested code please have a look :
DateTime? startDate = DateTime.Now;
DateTime? endDate = DateTime.Now.AddDays(5);
long differenceOfDays = 0;
if (startDate.HasValue && endDate.HasValue)
differenceOfDays = endDate.Value.Ticks - startDate.Value.Ticks;
int daysDifference = new TimeSpan(differenceOfDays).Days;
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;
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());
I'm converting a small MSAccess application to a web-based ASP.NET app, using C# 3.5. I was wondering what's the best way to work with dates in C#, when converting some of this VBA code over to C#.
Here is an example of the VBA Code:
Coverage1=IIf(IsNull([EffDate1]),0,IIf([CurrDate]<=[EndDate1],[CurrDate]-[EffDate1],[EndDate1]-[EffDate1]+1))
Here is what my current C# code looks like with the errors denoted in the commented code:
public DateTime CalculateCoverageOne(DateTime dateEffDateOne, DateTime dateCurrentDate, DateTime dateEndDateOne)
{
if (dateCurrentDate.Date <= dateEndDateOne.Date)
{
return null; //Get "cannot convert null to System.DateTime because it is a non-nullable value type" error
}
else
{
if (dateCurrentDate.Date <= dateEndDateOne)
{
return dateCurrentDate.Subtract(dateEffDateOne); //Gets error "cannot implicitly convert system.timepsan to system.datetime
}
else
{
return dateEndDateOne.Subtract(dateEffDateOne.AddDays(1)); //Gets error "cannot implicitly convert system.timepsan to system.datetime
}
}
}
cannot convert null to System.DateTime because it is a non-nullable value type" error
The DateTime type is a value type, which means that it cannot hold a null value. To get around this you can do one of two things; either return DateTime.MinValue, and test for that when you want to use the value, or change the function to return DateTime? (note the question mark), which is a nullable DateTime. The nullable date can be used like this:
DateTime? nullable = DateTime.Now;
if (nullable.HasValue)
{
// do something with nullable.Value
}
cannot implicitly convert system.timepsan to system.datetime
When you subtract a DateTime from another DateTime, the result is a TimeSpan, representing the amount of time between them. The TimeSpan does not represent a specific point in time, but the span itself. In order to get the date, you can use the Add method or the Subtract method overload of a DateTime object that accepts a TimeSpan. Exactly how that should look I can't say, since I don't know what the different dates in your code represent.
In the last case, you can simply use the return value from the AddDays method, but with a negative value (in order to subtract one day, instead of adding one):
return dateEffDateOne.AddDays(-1);
It looks like your VB is actually returning a time span, presumably in days. Here's the closest direct translation:
public TimeSpan CalculateCoverageOne(DateTime EffDate1, DateTime CurrDate, DateTime? EndDate1)
{
return (EndDate1 == null) ? TimeSpan.Zero :
(CurrDate < EndDate1) ? (CurrDate - EffDate1) :
(EndDate1.AddDays(1) - EffDate1);
}
If instead you just wanted a count of days, just return the TimeSpan's Days property:
public int CalculateCoverageOne(DateTime EffDate1, DateTime CurrDate, DateTime? EndDate1)
{
return ((EndDate1 == null) ? TimeSpan.Zero :
(CurrDate < EndDate1) ? (CurrDate - EffDate1) :
(EndDate1.AddDays(1) - EffDate1)).Days;
}
And for good measure, this is how I would clean up your final version:
public int CalculateCoverageOne(DateTime dateCurrentDate, DateTime dateEffectiveDate, DateTime dateEffDateOne, DateTime dateEndDateOne)
{
TimeSpan ts;
if (dateEffDateOne == DateTime.MinValue)
{
ts = TimeSpan.Zero;
}
else if (dateEffectiveDate <= dateEndDateOne)
{
ts = dateCurrentDate - dateEffDateOne;
}
else
{
ts = (dateEndDateOne - dateEffDateOne) + new TimeSpan(1, 0, 0, 0);
}
return ts.Days;
}
Get the TimeSpan, then subtract that from the DateTime to get the date you want. For your inner IF statement, it would look like this:
TimeSpan estSpan = dateCurrentDate.Subtract(dateEffDateOne);
return dateCurrentDate.Subtract(estSpan);
EDIT: You may also want to return DateTime.MaxValue and have the calling function check for the max value, instead of returning null.
DateTime is a value type. So, you cannot assign null to DateTime.
But you can use a special value like DateTime.MinValue to indicate whatever you were trying to indicate by null.
DateTime represents a date (and time), like "July 22, 2009". This means, you shouldn't use this type to represent time interval, like, "9 days". TimeSpan is the type intended for this.
dateCurrentDate.Subtract(dateEffDateOne) (or, equivalently, dateCurrentDate-dateEffDateOne) is a difference between two dates, that is, time interval. So, I suggest you to change return type of your function to TimeSpan.
TimeSpan is also a value type, so you could use, for instance, TimeSpan.Zero instead of null.
After some excellent answers (I've up-voted you guys), I've finally hammered out what I think is my answer. Turns out that returning an int, as the number of days, is what worked for me in this situation.
Thanks everyone, for providing your awesome answers. It helped me get on the right track.
public int CalculateCoverageOne(DateTime dateCurrentDate, DateTime dateEffectiveDate, DateTime dateEffDateOne, DateTime dateEndDateOne)
{
//Coverage1=
//IIf(IsNull([EffDate1]),0,
//IIf([CurrDate]<=[EndDate1],
//[CurrDate]-[EffDate1],
//[EndDate1]-[EffDate1]+1))
if (dateEffDateOne.Equals(TimeSpan.Zero))
{
return (TimeSpan.Zero).Days;
}
else
{
if (dateEffectiveDate <= dateEndDateOne)
{
return (dateCurrentDate - dateEffDateOne).Days;
}
else
{
return (dateEndDateOne - dateEffDateOne).Add(new TimeSpan(1, 0, 0, 0)).Days;
}
}
}