Если у вас много условий, вы можете переместить код в метод, чтобы улучшить читаемость / повторное использование:
albums = _albumRepository.Albums.Where(p => p.Match(searchString))
Затем создайте метод расширения для типа p
([113 ] или просто добавьте это к самому классу, если в вашем проекте будет больше смысла.
public static class AlbumsExtensions
{
public static bool Match(this Album album, string search)
{
// whatever complex logic you have stays here
var search = searchString.ToLower();
var result = p.Name.ToLower().Contains(search) ||
p.Artist.ToLower().Contains(search) ||
p.Genre.ToLower().Contains(search);
return result ;
}
}
И последнее, но не менее важное: обратите внимание, что сравнение строк не является тривиальным, если вы поддерживаете Unicode и несколько языков.
Для получения дополнительной информации взгляните на (например): Без учета регистра «Содержит (строка)»
Попробуйте это:
static int CountDays(DayOfWeek day, DateTime start, DateTime end)
{
TimeSpan ts = end - start; // Total duration
int count = (int)Math.Floor(ts.TotalDays / 7); // Number of whole weeks
int remainder = (int)(ts.TotalDays % 7); // Number of remaining days
int sinceLastDay = (int)(end.DayOfWeek - day); // Number of days since last [day]
if (sinceLastDay < 0) sinceLastDay += 7; // Adjust for negative days since last [day]
// If the days in excess of an even week are greater than or equal to the number days since the last [day], then count this one, too.
if (remainder >= sinceLastDay) count++;
return count;
}
Четыре года спустя я решил запустить тест:
[TestMethod]
public void ShouldFindFridaysInTimeSpan()
{
//reference: http://stackoverflow.com/questions/248273/count-number-of-mondays-in-a-given-date-range
var spanOfSixtyDays = new TimeSpan(60, 0, 0, 0);
var setOfDates = new List<DateTime>(spanOfSixtyDays.Days);
var now = DateTime.Now;
for(int i = 0; i < spanOfSixtyDays.Days; i++)
{
setOfDates.Add(now.AddDays(i));
}
Assert.IsTrue(setOfDates.Count == 60,
"The expected number of days is not here.");
var fridays = setOfDates.Where(i => i.DayOfWeek == DayOfWeek.Friday);
Assert.IsTrue(fridays.Count() > 0,
"The expected Friday days are not here.");
Assert.IsTrue(fridays.First() == setOfDates.First(i => i.DayOfWeek == DayOfWeek.Friday),
"The expected first Friday day is not here.");
Assert.IsTrue(fridays.Last() == setOfDates.Last(i => i.DayOfWeek == DayOfWeek.Friday),
"The expected last Friday day is not here.");
}
Мое использование TimeSpan
немного излишне - на самом деле я хотел запросить TimeSpan
напрямую.
private System.Int32 CountDaysOfWeek(System.DayOfWeek dayOfWeek, System.DateTime date1, System.DateTime date2)
{
System.DateTime EndDate;
System.DateTime StartDate;
if (date1 > date2)
{
StartDate = date2;
EndDate = date1;
}
else
{
StartDate = date1;
EndDate = date2;
}
while (StartDate.DayOfWeek != dayOfWeek)
StartDate = StartDate.AddDays(1);
return EndDate.Subtract(StartDate).Days / 7 + 1;
}
У меня была похожая проблема для отчета. Мне нужно было количество рабочих дней между двумя датами. Я мог бы перебрать даты и посчитать, но мое дискретное обучение математике не позволило бы мне. Вот функция, которую я написал в VBA, чтобы получить количество рабочих дней между двумя датами. Я уверен, что .net имеет аналогичную функцию WeekDay.
1
2 ' WorkDays
3 ' returns the number of working days between two dates
4 Public Function WorkDays(ByVal dtBegin As Date, ByVal dtEnd As Date) As Long
5
6 Dim dtFirstSunday As Date
7 Dim dtLastSaturday As Date
8 Dim lngWorkDays As Long
9
10 ' get first sunday in range
11 dtFirstSunday = dtBegin + ((8 - Weekday(dtBegin)) Mod 7)
12
13 ' get last saturday in range
14 dtLastSaturday = dtEnd - (Weekday(dtEnd) Mod 7)
15
16 ' get work days between first sunday and last saturday
17 lngWorkDays = (((dtLastSaturday - dtFirstSunday) + 1) / 7) * 5
18
19 ' if first sunday is not begin date
20 If dtFirstSunday <> dtBegin Then
21
22 ' assume first sunday is after begin date
23 ' add workdays from begin date to first sunday
24 lngWorkDays = lngWorkDays + (7 - Weekday(dtBegin))
25
26 End If
27
28 ' if last saturday is not end date
29 If dtLastSaturday <> dtEnd Then
30
31 ' assume last saturday is before end date
32 ' add workdays from last saturday to end date
33 lngWorkDays = lngWorkDays + (Weekday(dtEnd) - 1)
34
35 End If
36
37 ' return working days
38 WorkDays = lngWorkDays
39
40 End Function
Добавьте наименьшее возможное число, чтобы первый день стал понедельником. Вычтите наименьшее возможное число, чтобы сделать последний день понедельником. Рассчитайте разницу в днях и разделите на 7.
Какой-либо конкретный язык и, следовательно, формат даты?
Если даты представлены в виде количества дней, то большая часть ответа - разница между двумя значениями плюс одно (день) и делением на 7. Если обе даты окончания являются указанным днем, добавьте одну.
Отредактировано: исправлено «по модулю 7», чтобы «делить на 7» - спасибо. И это целочисленное деление.
Вот некоторый псевдокод:
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
, Где DifferenceInDays
возвраты End - Start
в днях, и DayOfWeek
возвраты день недели как целое число. Действительно не имеет значения, какое отображение DayOfWeek
использование, пока это увеличивается и совпадает с DayImLookingFor
.
Примечание, что этот алгоритм принимает диапазон дат, является содержащим. Если End
не должна быть часть диапазона, необходимо будет скорректировать алгоритм немного.
Перевод в C# оставляют как осуществление для читателя.
Интересно посмотреть на различный алгоритм для вычисления дня недели, и @Gabe Hollombe, указывающий на WP на предмете, был прекрасной идеей (и я не забываю реализовывать Конгруэтность Zeller в КОБОЛе приблизительно двадцать лет назад), но это скорее приехало строка вручения кому-то проект часов, когда все, что они спросили, во сколько это было.
В C#:
private int CountMondays(DateTime startDate, DateTime endDate)
{
int mondayCount = 0;
for (DateTime dt = startDate; dt < endDate; dt = dt.AddDays(1.0))
{
if (dt.DayOfWeek == DayOfWeek.Monday)
{
mondayCount++;
}
}
return mondayCount;
}
Это, конечно, не оценивает дату окончания "Mondayness", поэтому если это было желаемо, сделайте для цикла, оценивают
dt < endDate.AddDays(1.0)
Так как Вы используете C# при использовании C#3.0 можно использовать LINQ.
Принятие у Вас есть Array/List/IQueryable и т.д., который содержит Ваши даты как типы DateTime:
DateTime[] dates = { new DateTime(2008,10,6), new DateTime(2008,10,7)}; //etc....
var mondays = dates.Where(d => d.DayOfWeek == DayOfWeek.Monday); // = {10/6/2008}
Добавленный:
Не уверенный, если Вы означали группировать их и считать их, но здесь - как сделать это в LINQ также:
var datesgrouped = from d in dates
group d by d.DayOfWeek into grouped
select new { WeekDay = grouped.Key, Days = grouped };
foreach (var g in datesgrouped)
{
Console.Write (String.Format("{0} : {1}", g.WeekDay,g.Days.Count());
}
Преобразуйте даты в Юлианский номер дня, затем немного подсчитайте. Поскольку понедельник - нулевой мод 7, вы можете сделать расчет следующим образом:
JD1=JulianDayOf(the_first_date)
JD2=JulianDayOf(the_second_date)
Round JD1 up to nearest multiple of 7
Round JD2 up to nearest multiple of 7
d = JD2-JD1
nMondays = (JD2-JD1+7)/7 # integer divide
I have had the same need today. I started with the cjm function since I don't understand the JonB function and since the Cyberherbalist function is not linear.
I had have to correct
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
to
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayImLookingFor is between Start.Day and End.Day
With the between function that return true if, starting from the start day, we meet first the dayImLookingFor before the endDay.
I have done the between function by computing the number of day from startDay to the other two days:
private int CountDays(DateTime start, DateTime end, DayOfWeek selectedDay)
{
if (start.Date > end.Date)
{
return 0;
}
int totalDays = (int)end.Date.Subtract(start.Date).TotalDays;
DayOfWeek startDay = start.DayOfWeek;
DayOfWeek endDay = end.DayOfWeek;
///look if endDay appears before or after the selectedDay when we start from startDay.
int startToEnd = (int)endDay - (int)startDay;
if (startToEnd < 0)
{
startToEnd += 7;
}
int startToSelected = (int)selectedDay - (int)startDay;
if (startToSelected < 0)
{
startToSelected += 7;
}
bool isSelectedBetweenStartAndEnd = startToEnd >= startToSelected;
if (isSelectedBetweenStartAndEnd)
{
return totalDays / 7 + 1;
}
else
{
return totalDays / 7;
}
}