Query List of DateTime objects between hours - c#

I have a list of DateTime Objects, this objects have a StarteDate and a EndDate. No I want to get all items that occur within a StartHour and an EndHour.
My code so far:
var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate.Date
&& x.Start.Hour >= startHour && x.End.Hour <= endHour);
This works as long as the start hor of an item is equal or larger than the startHour provided. However if for example the startHour = 09:00 and an item has Start = 8:00 and End = 10:00 it is ignored.
How can I include items that have a start hour between start hour and end hour?
Thank you!

var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate &&
(((x.Start.Hour >= startHour && x.Start.Hour < endHour) ||
(x.End.Hour > startHour && x.End.Hour <= endHour)) ||
(x.Start.Hour < startHour && x.End.Hour > endHour)));
Check to see if either the start of the event is in the time window, or the end of the event is in the time window, or whether the event overlaps the time window. (Added a fix to prevent inclusive end and start times)
Testing some more, it can be shrunk to this:
var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate &&
(x.Start.Hour < endHour && x.End.Hour > startHour));

Check if this works :
var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate.Date
&& x.Start.Hour >= startHour && x.Start.Hour <= endHour);

Related

Select Query Count LINQ C# Unity Not Working Correctly

Could someone tell me why this query return a wrong value ?
First I generate 30 data at Player.estateagent. The Date must until 28/05.
System.DateTime Now = System.DateTime.Now;
System.DateTime thedate;
thedate = Now;
System.DateTime today = System.DateTime.Now;
for (int i = 1; i <= 30; i++) {
Player.estateagent.Add (new classBundle (thedate, false));
thedate = thedate.AddDays (1);
Debug.Log ("DATE : " + Player.estateagent [i - 1].Date);
}
int count = Player.estateagent.Where (j => {
return j.Complete == false && today.Date <= j.Date.Date;
}).Select (j=> j.Date.Date).Count ();
Debug.Log(count); // Here return 30, It must be 1
When i count i got 30 not 1. It should return 1 because i have query
where j.complete == false && today.Date <= j.Date.Date
Can someone explain what mistake that i done ?
Thanks
Yes, So far I have asked a wrong question. This is just misunderstood about the logic.
The code i am provide above is running without an error. And the logic is right too.
The result is right with 30.
But i want to have a result which Equal and Greater ( <= ) than the Player.estateagent => Date Compire to today date.
So i just need to do today.Date >= j.Date.Date.
Just like that.

Calculate business days in future to send reminder emails

I am working on this employee performance review application. I need to send out reminder emails when the user has left 3 and 1 business days before the end of the 15 business day period.
Here is how I plan on doing it:
I have the Last Modified Date for each Review which I should be able to use to find out 15 business days in future(call it deadLineToSubmit for our example). Once I got deadLineToSubmit I should check to see if currentDate + 3 days(date) == deadLineToSubmit Then add that review to my list which I will be using to send email.
I have a function called GetByDayPrior where I am sending values 3 and 1 to check if user have left 3 business days or 1. Below is the code:
public List<int> GetByDaysPrior(int daysPrior)
{
List<int> response = new List<int>();
using (DAL.HumanResourcesEntities context = new DAL.HumanResourcesEntities())
{
DateTime currentDate = DateTime.Now.Date;
var lastModifiedDate = context.Reviews
.Where(s => s.IsActive == false)
.Where(s => s.ReviewStatusId == (int)ReviewStatuses.EmployeeSignature)
.Select(v => v.ModifiedDate)
.ToList();
AddBusinessDays(lastModifiedDate, daysPrior);
var lastRuntime = context.ApplicationRuntimeVariables.Where(y => y.ParameterName == "RemindersSentDT").Select(x => x.ParameterValue).FirstOrDefault().Date;
DateTime deadLineToSubmitReview = currentDate.AddDays(daysPrior).Date;
if (lastRuntime.AddHours(24).Date <= currentDate) //should it be == current date ?
{
var reviewIDs = context.Reviews
.Where(s => s.ModifiedDate < deadLineToSubmitReview)
.Where(s => s.ReviewStatusId == (int)ReviewStatuses.EmployeeSignature) //Check to make sure reminders only go when Review Status is Employee Signature
.Where(s => s.IsActive == false)
.Select(v => v.ReviewId)
.ToList();
response = reviewIDs.ToList();
}
return response;
}
}
I have another function called AddBusinessDays should give me the deadLineToSubmit when I pass in LastModifiedDate and 15 days as parameter. But currently its not working because firstly I cannot find out how to pass List of DataTime as a paramater in this function. Also when I defined date parameter in AddBusinessDays as List now all the instances of date and DayOfWeek are complanining
"Error 32 Cannot implicitly convert type
'System.Collections.Generic.List' to
'System.DateTime'
Below is my AddBusinessDays function.
public static DateTime AddBusinessDays(List<DateTime> date, int days)
{
if (days < 0)
{
throw new ArgumentException("days cannot be negative", "days");
}
if (days == 0) return date;
if (date.DayOfWeek == DayOfWeek.Saturday)
{
date = date.AddDays(2);
days -= 1;
}
else if (date.DayOfWeek == DayOfWeek.Sunday)
{
date = date.AddDays(1);
days -= 1;
}
date = date.AddDays(days / 5 * 7);
int extraDays = days % 5;
if ((int)date.DayOfWeek + extraDays > 5)
{
extraDays += 2;
}
return date.AddDays(extraDays);
}
Here's what I need to know: How to send DateTime List as parameter in AddBusinessDays function. How to make AddBusinessDays function work because now we are passing list instead of single dateTime. Is my thinking logic correct to solve this issue ?
Thanks a Lot! :)
date is a list and not a single date.
You can make an operation on all items of the list by using Select
for example:
lastModifiedDate = AddBusinessDays(lastModifiedDate, daysPrior);
Step 1: Convert your function to receive a single date
private static DateTime AddBusinessDays(DateTime date, int days)
{
if (days < 0)
{
throw new ArgumentException("days cannot be negative", "days");
}
if (days == 0) return date;
if (date.DayOfWeek == DayOfWeek.Saturday)
{
date = date.AddDays(2);
days -= 1;
}
else if (date.DayOfWeek == DayOfWeek.Sunday)
{
date = date.AddDays(1);
days -= 1;
}
date = date.AddDays(days / 5 * 7);
int extraDays = days % 5;
if ((int)date.DayOfWeek + extraDays > 5)
{
extraDays += 2;
}
return date.AddDays(extraDays);
}
Step 2: Use the single date function for the list of dates
public static List<DateTime> AddBusinessDays(List<DateTime> date, int days)
{
return date.Select(d => AddBusinessDays(d, days)).ToList();
}

If Statement To Check Dates

I have an 'IF' statement but I want the condition to check that the date of my object is not less than todays date but I can not figure out how to do this at all.
Code
private List<Web.Services.Entities.Generic.Expenditure> getTransactions(int Id, int AccountId, string Identifier)
{
if (Details != null)
{
foreach (var ABC in Details.Info.ABC)
{
if (ABC.Type == "Test" && ABC.Value.Value > 0)
{
int j = 1;
if (ABC.Frequency == "Monthly")
{
j = 3;
}
for (var i = 0; i < j; i++)
{
List.Add(new Web.Services.Entities.Generic.Expenditure
{
Amount = ABC.RegularIncome.Value * -1,
Description = "Income (" + ABC.Frequency + ")",
DueDate = (DateTime)ABC.NextDate.Value.AddMonths(i)
});
}
}
}
}
}
I tried to declare my (DateTime)ABC.NextDate.Value as a VAR above the following IF and then add to if (ABC.Type == "ABC" && ABC.Value.Value > 0) but I got the following error:
operator '&& ' cannot be applied to operands of type 'bool' and
'system.datetime'
I need to add another condition to the above IF and not replace the '0' as this is checking another value in what is returned.
To test a nullable date you do the following:
if (dateTimeToBeTested.Value.Date >= DateTime.Now.Date)
By using the .Date property, you are forcing the DateTime to midnight of the date in question, so time differences will be ignored.
To use this in your example above, you can do the following:
if (ABC.Type == "Test" && ABC.Value.Value > 0 && dateTimeToBeTested.Value.Date >= DateTime.Now.Date)
Use DateTime.Now to compare ABC.Value.Value with current date.
if (ABC.Type == "Test" && ABC.Value.Value > DateTime.Now)
Edit after question update with more required details and updated if statement.
System.Nullable' does not contain a definition for 'Date' and no
extension method 'Date' accepting...
You need to use DateTime.Value to access the Date property of nullable DateTime. Before using Date property you must check if DateTime variable has value. You can use .HasValue to ensure you have value for nullable DateTime.
Once you are sure that your datetime variable has values using .HasValue you can safely use DateProperty so you would use ABC.NextDate.Value instead of ABC.NextDate to access Date Property.
if (ABC.Type == "Test" && ABC.Value.Value > 0 && ABC.NextDate.HasValue && ABC.NextDate.Value.Date >= DateTime.Now.Date)

validate selected date in selected month and year in dropdowns in client side

I am working with my mvc 4 application.Here I have Day ,Month ,Year dropdowns to select a date of birth. Now I want to validate a selected date in a selected month and year (especially February 29,28 , and for all month). Is there any defined jquery or javascript functions for that?
Please help.
function isDate(txtDate) {
var currVal = txtDate;
if (currVal == '')
return false;
//Declare Regex
var rxDatePattern = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
var dtArray = currVal.match(rxDatePattern); // is format OK?
if (dtArray == null)
return false;
//Checks for dd/mm/yyyy format.
var dtDay = dtArray[1];
var dtMonth = dtArray[3];
var dtYear = dtArray[5];
if (dtMonth < 1 || dtMonth > 12)
return false;
else if (dtDay < 1 || dtDay > 31)
return false;
else if ((dtMonth == 4 || dtMonth == 6 || dtMonth == 9 || dtMonth == 11) && dtDay == 31)
return false;
else if (dtMonth == 2) {
var isleap = (dtYear % 4 == 0 && (dtYear % 100 != 0 || dtYear % 400 == 0));
if (dtDay > 29 || (dtDay == 29 && !isleap))
return false;
}
return true;
}
This will work in this format "dd/MM/yyyy".
<script type="text/javascript">
function checkdate(input){
var validformat=/^\d{2}\/\d{2}\/\d{4}$/ //Basic check for format validity
var returnval=false
if (!validformat.test(input.value))
alert("Invalid Date Format. Please correct and submit again.")
else{
var monthfield=input.value.split("/")[0]
var dayfield=input.value.split("/")[1]
var yearfield=input.value.split("/")[2]
var dayobj = new Date(yearfield, monthfield-1, dayfield)
if ((dayobj.getMonth()+1!=monthfield)||(dayobj.getDate()!=dayfield)||(dayobj.getFullYear()!=yearfield))
alert("Invalid Day, Month, or Year range detected. Please correct and submit again.")
else
returnval=true
}
if (returnval==false) input.select()
return returnval
}
</script>
u call this function onClick of submit button and you have to pass the date in mm/dd/yyyy format to this function . it will validate all dates. if you are facing issue then plz reply me .

Query upcoming birthdays

I'd like to query my customers for the ones, whose birthdays are yet to come.
I've tried this query, and it - of course - has failed breathtakingly:
Addresses.Where(adr => adr.DateOfBirth != null && adr.DateOfBirth.Value >
DateTime.Now).Take(15).ToList();
Of course this can't work properly (not if you're born in the future) and I'd like to know how I can query my Nullable<DateTime> without a year?
You can do it in one line like this:
context.Addresses.Where(adr => adr.DateOfBirth != null).OrderBy(adr => EntityFunctions.DiffDays(DateTime.Today, EntityFunctions.AddYears(adr.DateOfBirth, EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today) + ((adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month)) ? 1 : 0)))).Take(15).ToList();
Or in a more readable format:
var query = from adr in context.Addresses
where adr.DateOfBirth != null
let diffYears = EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today)
let birthdayOccurred = adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month)
let nextBirthdate = EntityFunctions.AddYears(adr.DateOfBirth, diffYears + (birthdayOccurred ? 1 : 0))
let daysToBirthdate = EntityFunctions.DiffDays(DateTime.Today, nextBirthdate)
orderby daysToBirthdate
select adr;
var result = query.Take(15).ToList();
I'm not sure you can do this as a one-liner. Certainly not with any degree of clarity.
The needed steps are:
Create an ordered list containing only the birthdates where the
month/day comes after today.
Create an ordered list containing only the birthdates where the month/day is before today.
Append the second list to the first one, you now have a single list, sorted in
birthday order.
Take the first 15.
I think the C# code would look something like this (You might need to add a List or two.)
var list1 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month > DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day >= DateTime.Today.Day))).ToList();
var list2 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month < DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day < DateTime.Today.Day))).ToList();
var fullList = list1.Add(list2);
Im not familiar with Linq, I'll try to help with some pseudocode.
Most important condition should look like this:
Date(CurrentDate.Year, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate
|| ' OR
Date(CurrentDate.Year + 1, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate
This will work 31 December too.
Alternative:
// consider this as pseudocode, I didnt tested that in C#
function GetNextBirthday(DateTime DateOfBirth)
{
int yearOfNextBirthday;
int birthdayMMDD = DateOfBirth.Month*100 + DateOfBirth.Day;
int todayMMDD = CurrentDate.Month*100 + CurrentDate.Day;
if (birthdayMMDD >= todayMMDD)
{
yearOfNextBirthday = CurrentDate.Year; // this year
}
else
{
yearOfNextBirthday = CurrentDate.Year + 1; // next year
}
DateTime nextBirthday;
// you have to write this line yourself, i dont remember how to make date from Y, M, D
nextBirthday = DateFromYMD(yearOfNextBirthday, DateOfBirth.Month, DateOfBirth.Day);
return nextBirthday;
}
Here is my entry for "one liner":
DateTime now = DateTime.Now;
var next15 =
from a in db.Addresses
where a.DateOfBirth != null
let diff = EntityFunctions.DiffSeconds(
EntityFunctions.AddYears(now, -EntityFunctions.DiffYears(a.DateOfBirth, now)),
a.DateOfBirth)
orderby diff >= 0 ? diff : diff + 366*24*60*60
select new a;
var res = next15.Take(15).ToList();
Just tested with SQL Database - and it works like charm ;)
Try something like this; (this is working - I've tested)
//A mock up value for comparison (as DayOfYear not supported in Linq)
int doy = DateTime.Today.Month * 31 + DateTime.Today.Day;
var results = Addresses.Where(a => a.DateOfBirth != null)
.OrderBy( a =>
(a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day) +
(a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day > doy ? 0 : 400 ))
.Take(15).ToList();
Here's the same solution as #Aducci but with nullable date and the DBFunctions, as EntityFunctions became deprecated.
pacientes = from paciente in pacientes
where paciente.Nascimento != null
let diffYears = DbFunctions.DiffYears(paciente.Nascimento, DateTime.Today)
let birthdayOccurred = paciente.Nascimento.Value.Month < DateTime.Today.Month
|| (paciente.Nascimento.Value.Day <= DateTime.Today.Day && paciente.Nascimento.Value.Month == DateTime.Today.Month)
let nextBirthdate = DbFunctions.AddYears(paciente.Nascimento, diffYears + (birthdayOccurred ? 1 : 0))
let daysToBirthdate = DbFunctions.DiffDays(DateTime.Today, nextBirthdate)
orderby daysToBirthdate
select paciente;

Categories