Find TotalDays between two Datetime? variables - c#

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;

Related

C# DateTime and String value condition check

I have a problem.
This is not working
> var from = "";
> StartDTime = Convert.ToDateTime(from);
This is working
> var from = "2021-10-05";
> StartDTime = Convert.ToDateTime(from);
Some time I'm sending Date Value, but sometime in not sending Date Value.in that time from variable pass as a empty string. I want to set if from variable is = "" then need to set default Date Value.so how can I resolve this?. Please help me guys. Thank you
A safe way of doing that would be:
StartDTime = string.IsNullOrEmpty(from) ? DateTime.Now : DateTime.Parse(from);
But if you have control over the code passing the "from" variable, you can declare it as nullable DateTime, then your code would look like this:
DateTime? from = null;
var StartDTime = from.HasValue ? from.Value : DateTime.Now;
Which for short would be:
StartDTime = from ?? DateTime.Now;
DateTime.TryParse will do the job for you:
for example:
DateTime dateTime;
var from = "";
DateTime.TryParse(from, out dateTime);
One-liner, with only the validation you specify:
StartDTime = from == "" ? new DateTime() : Convert.ToDateTime(from);
It's not ellegant, but works.
var from = "";
if(from == ""){ from = DateTime.MinValue.ToString(); }
DateTime StartDTime = Convert.ToDateTime(from);
But i think that a nullable DateTime would be more elegant, like this:
var from = null;
DateTime? StartDTime = from;
Or you can set a default date, like this:
var from = null;
DateTime? StartDTime = from ?? YourDefaultDate;
Convert methods either successfully convert the string passed to it, or throws an error, that's the way it's supposed to work. For most data types there are also TryParse methods that return true/false based on if it converted successfully and have an output variable which will be DateTime.MinValue if it failed. This is how I would handle your situation:
DateTime startDTime;
string from = "";
if (!DateTime.TryParse(from, out startDTime)){
startDTime = DateTime.Now;
}
This will set the startTime to the date passed in from, but if no date was passed it sets it to the current date and time - if you want a different default value, that replaces new DateTime() and if your default should be January 1, 0001, then you can just use the TryParse part directly, since that's the automatic default for a failed TryParse.

Converting short? to TimeSpan

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

Comparing Datetime? inside Linq Expression

i am trying to return queries from a DB using Entity Framework and Linq on a Nullable DateTime field.
I have the following code;
DateTime? from = new DateTime(year, month, 1);
DateTime? to = from.Value.AddMonths(1);
return context.Where<Job>(
x =>
x.NextDueDate?.Date >= from?.Date &&
x.NextDueDate?.Date <= to?.Date).ToList();
Where Job is (reduced for brevity);
public class Job : AuditableEntity
{
...
public DateTime? NextDueDate { get; set; }
I tried this from the following stack link;
Linq expression with nullable DateTime
However, when I try this I am getting the following error;
An expression tree lambda may not contain a null propagating operator
Can anyone explain a solution to this please?
As the exception message said you cannot use ?.
// First day of a month. E.g. 2/1/2018 12:00:00 AM
DateTime from = new DateTime(year, month, 1);
// Last day of a month and end of that day. E.g. 2/28/2018 11:59:59 PM
DateTime to = from.AddMonths(1).AddTicks(-1);
return context.Where<Job>(
x =>
x.NextDueDate != null &&
x.NextDueDate >= from &&
x.NextDueDate <= to).ToList();
You are setting public DateTime? NextDueDate { get; set; }. So the default value won't be null.
Please try below code, because the date time value won't be null in code even when you fetch the null date time column from db. Which have a default value equal to 1/1/0001 12:00:00 AM.
DateTime from = new DateTime(year, month, 1);
DateTime to = from.Value.AddMonths(1);
DateTime dateTimeDefault = default(DateTime);
return context.Where<Job>(
x =>
x.NextDueDate.Date != dateTimeDefault
x.NextDueDate.Date >= from.Date &&
x.NextDueDate.Date <= to.Date).ToList();

Operator >= cannot be applied to operands of type string and datetime

The user enters two parameters in the url which are the start date and end date and they are entered in the format yyyyMMddhhmm as a string. I'm attempting to take these strings and turn them into dates so I can query my database.
[ResponseType(typeof(Detail))]
public IHttpActionResult GetDetail(string StartDate, string EndDate)
{
DateTime StartDateTime;
DateTime EndDateTime;
StartDateTime = new DateTime();
EndDateTime = new DateTime();
StartDateTime = DateTime.ParseExact(StartDate, "yyyyMMddhhmm", null);
EndDateTime = DateTime.ParseExact(EndDate, "yyyyMMddhhmm", null);
var detail = from a in db.Details where (a.callDate >= StartDateTime && a.callDate <= EndDateTime) select a;
var Response = new DetailResponse() { status = true, calls = detail };
return Ok(response);
}
However I get the error that >= can't be used in datetime and strings.
EDIT:
For the sake of one of the answer I'm including a model class I'm using to display the data.
DetailResponse.cs
public class DetailResponse
{
public bool status { get; set; }
public string statusMessage { get; set; }
public IQueryable<Detail> calls { get; set; }
}
Probably this is happening, because callDate is a string. So you can't compare a string with a datetime. The solution to this problem is to have the same type. That being said I would convert a.callDate to a DateTime.
However, I think that it would be better you change the data type of callDate in the database level. Undoubtedly, this is a personal opinion. So you don't have to follow it. Doing so your code will not need any change.
Now, in terms of code the solution I suggested above is the following:
var allDetails = db.Details.AsEnumerable();
var details = from detail in details
let callDate = DateTime.ParseExact(detail.callDate, "yyyyMMddhhmm", null)
where callDate >= StartDateTime
&& callDate <= EndDateTime
select detail;
Update
As we concluded in comments, we had to call the AsEnumerable, in order the above query to work. Why is this needed?
Borrowing Jon Skeet's words from Reimplementing Linq to Objects: Part 36 – AsEnumerable
Now it’s not entirely uncommon to want to perform some aspects of the
query in the database, and then a bit more manipulation in .NET –
particularly if there are aspects you basically can’t implement in
LINQ to SQL (or whatever provider you’re using). For example, you may
want to build a particular in-memory representation which isn’t really
amenable to the provider’s model.
The DateTime.ParseExact cannot be translated properly in a database method.
Your comparison is failing because the date in your database is of type string, try doing like this:
[ResponseType(typeof(Detail))]
public IHttpActionResult GetDetail(string StartDate, string EndDate)
{
DateTime StartDateTime = DateTime.ParseExact(StartDate, "yyyyMMddhhmm", null);
DateTime EndDateTime = DateTime.ParseExact(EndDate, "yyyyMMddhhmm", null);
var detail = from a in db.Details where (DateTime.ParseExact(a.callDate, "yyyyMMddhhmm", null) >= StartDateTime &&
DateTime.ParseExact(a.callDate, "yyyyMMddhhmm", null) <= EndDateTime) select a;
}
However you are probably best off chaning the type of your callDate to a date instead of a string.
What does your schema look like? is callDate a string? you may need to convert callDate to a DateTime before you can do the comparison.
var detail = from a in db.Details where (Convert.ToDateTime(a.callDate) >= StartDateTime && Convert.ToDateTime(a.callDate) <= EndDateTime) select a;
As has already been said, you can't compare a string to a DateTime, however, given that the date format is
yyyyMMddhhmm
(ie. year month day hour minute) where the values are all numeric and go from least varying -> most varying you will be safe doing a string comparison:
var detail = from a in db.Details where (a.callDate >= StartDate && a.callDate <= EndDate) select a;
This is because "201601010101" is less than "201612312359" when comparing strings (in the same way that "a" is less than "b").
This will save you converting the data to DateTime.
Having said that, by doing the conversion you are validating the data and can show an error if it's not in the right format.

Difference between DateTimeOffset?(Nullable) and DateTimeOffset.Now

How can I calculate the time between between a nullable DateTimeOffset? to DateTimeOffset.Now ?
I need the result like "x day y hours ago"
I started by doing something like this.
var creationTime = //A nullable DateTimeOffset on Database
var difference = DateTimeOffset.Now.Subtract(creationTime);
But since creationTime is a nullable time, it gives me an error and I can't really find the difference.
Depending on what difference you expect from a NULL database value you can simply handle this using the ?? operator:
DateTimeOffset? creationTime = null; // A nullable DateTimeOffset on Database
DateTimeOffset rightnow = DateTimeOffset.Now;
DateTimeOffset somewhen = creationTime ?? rightnow; // if NULL, it's NOW
var difference = rightnow.Subtract(somewhen);
(could of course be shortend to using ?? just when reading the database value)
First test if it has a value with HasValue and if it does use the Value property to get the actual value
if(creationTime.HasValue)
TimeSpan difference = DateTimeOffset.Now.Subtract(creationTime.Value);
Or if you have a default value in mind you can use GetValueOrDefault
TimeSpan difference = DateTimeOffset.Now.Subtract(creationTime.GetValueOrDefault(default));
A final option would be to just use the - operator.
TimeSpan? difference = DateTimeOffset.Now - creationTime;
but note that difference will be a TimeSpan? and will be null if creationTime is null.
Just in case anyone comes across this issue, here is the extension method that I came up with the help of above answers.
namespace Extensions{
public static class DateExtensions
{
public static string GetDifferenceTillNow(this DateTimeOffset? datetimeoffset) {
DateTimeOffset? creationTime = datetimeoffset;
DateTimeOffset rightnow = DateTimeOffset.Now;
DateTimeOffset somewhen = creationTime ?? rightnow;
TimeSpan difference = rightnow.Subtract(somewhen);
return difference.Days.ToString() +" days & " + difference.Hours.ToString() + " hours ago";
}
}
}

Categories