문제
날짜 범위가 주어지면 월요일 (또는 화요일, 수요일 등)이 그 범위에 있는지 알아야합니다.
현재 C#에서 일하고 있습니다.
해결책
이 시도:
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;
}
다른 팁
C#을 사용하고 있으므로 C#3.0을 사용하는 경우 LINQ를 사용할 수 있습니다.
날짜가 DateTime 유형으로 포함 된 배열/목록/IQueryable 등이 있다고 가정합니다.
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());
}
요일을 계산하기위한 다른 알고리즘을 보는 것은 재미 있고, @Gabe Hollombe는 주제에 대한 WP를 가리키는 것이 좋은 아이디어였습니다 (그리고 나는 구현을 기억합니다. Zeller의 합동 약 20 년 전 코볼에서), 그러나, 그것은 누군가에게 시계의 청사진을 건네주는 선을 따라 갔다.
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;
}
물론 이것은 "월요일"에 대한 종료 날짜를 평가하지 않으므로 이것이 원하는 경우 for 루프 평가를하십시오.
dt < endDate.AddDays(1.0)
여기 몇 가지 의사 코드가 있습니다.
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#로 번역하는 것은 독자의 운동으로 남겨집니다.
특정 언어와 날짜 형식이 있습니까?
날짜가 일의 수로 표시되면 두 값과 1 일 (일)과 7으로 나누는 차이는 대부분의 답변입니다. 두 종료 날짜가 문제의 날이면 하나를 추가하십시오.
편집 : 'Modulo 7'을 '7로 나누기' - 감사합니다. 감사합니다. 그리고 그것은 정수 부서입니다.
LINQ를 사용 하여이 문제를 해결하는 약간 쉬운 방법을 발견했습니다.
public static int NumberOfFridays(DateTime start, DateTime end)
{
return start.GetDaysInBetween(end, inclusive: true).Count(d => d.DayOfWeek == DayOfWeek.Friday);
}
도움이되기를 바랍니다.
가장 작은 숫자를 추가하여 첫 날을 월요일에 만듭니다. 마지막 날을 월요일에 만들기 위해 가능한 가장 작은 숫자를 빼십시오. 일의 차이를 계산하고 7로 나눕니다.
날짜를 줄리안의 날 번호로 변환 한 다음 약간의 수학을하십시오. 월요일은 제로 모드 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
나는 오늘 똑같은 필요를 가졌다. 나는 시작했다 CJM 내가 이해하지 못하기 때문에 기능 존브 기능과 이후 사이버 밸리스트 함수는 선형이 아닙니다.
나는 수정해야했다
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
에게
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayImLookingFor is between Start.Day and End.Day
시작일부터 시작하는 경우 true를 반환하는 사이의 기능 중에서 우리는 끝날 전에 Dayimloking을 먼저 만납니다.
나는 시작부터 다른 이틀까지 하루의 수를 계산하여 사이에서 기능 사이를 수행했습니다.
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;
}
}
public List<DateTime> GetSelectedDaysInPeriod(DateTime startDate, DateTime endDate, List<DayOfWeek> daysToCheck)
{
var selectedDates = new List<DateTime>();
if (startDate >= endDate)
return selectedDates; //No days to return
if (daysToCheck == null || daysToCheck.Count == 0)
return selectedDates; //No days to select
try
{
//Get the total number of days between the two dates
var totalDays = (int)endDate.Subtract(startDate).TotalDays;
//So.. we're creating a list of all dates between the two dates:
var allDatesQry = from d in Enumerable.Range(1, totalDays)
select new DateTime(
startDate.AddDays(d).Year,
startDate.AddDays(d).Month,
startDate.AddDays(d).Day);
//And extracting those weekdays we explicitly wanted to return
var selectedDatesQry = from d in allDatesQry
where daysToCheck.Contains(d.DayOfWeek)
select d;
//Copying the IEnumerable to a List
selectedDates = selectedDatesQry.ToList();
}
catch (Exception ex)
{
//Log error
//...
//And re-throw
throw;
}
return selectedDates;
}
이것은 날짜 범위 내에서 일주일의 매일 몇 번이나 발생하는지를 보여주는 정수 모음을 반환합니다.
int[] CountDays(DateTime firstDate, DateTime lastDate)
{
var totalDays = lastDate.Date.Subtract(firstDate.Date).TotalDays + 1;
var weeks = (int)Math.Floor(totalDays / 7);
var result = Enumerable.Repeat<int>(weeks, 7).ToArray();
if (totalDays % 7 != 0)
{
int firstDayOfWeek = (int)firstDate.DayOfWeek;
int lastDayOfWeek = (int)lastDate.DayOfWeek;
if (lastDayOfWeek < firstDayOfWeek)
lastDayOfWeek += 7;
for (int dayOfWeek = firstDayOfWeek; dayOfWeek <= lastDayOfWeek; dayOfWeek++)
result[dayOfWeek % 7]++;
}
return result;
}
또는 첫 번째를 할 수있는 약간의 변형.
public static Dictionary<DayOfWeek, int> TotalDaysOfWeeks(this DateTime firstDate, DateTime lastDate)
{
var totalDays = lastDate.Date.Subtract(firstDate.Date).TotalDays + 1;
var weeks = (int)Math.Floor(totalDays / 7);
var resultArray = Enumerable.Repeat<int>(weeks, 7).ToArray();
if (totalDays % 7 != 0)
{
int firstDayOfWeek = (int)firstDate.DayOfWeek;
int lastDayOfWeek = (int)lastDate.DayOfWeek;
if (lastDayOfWeek < firstDayOfWeek)
lastDayOfWeek += 7;
for (int dayOfWeek = firstDayOfWeek; dayOfWeek <= lastDayOfWeek; dayOfWeek++)
resultArray[dayOfWeek % 7]++;
}
var result = new Dictionary<DayOfWeek, int>();
for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++)
result[(DayOfWeek)dayOfWeek] = resultArray[dayOfWeek];
return result;
}
보고서에 대해 비슷한 문제가있었습니다. 두 날짜 사이에 근무일이 필요했습니다. 나는 날짜를 순환하고 계산할 수 있었지만, 나의 개별 수학 훈련은 나를 허용하지 않을 것입니다. 다음은 VBA에서 쓴 기능이 두 날짜 사이에 근무일 수를 얻습니다. .NET은 비슷한 평일 기능을 가지고 있다고 확신합니다.
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
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;
}
4 년 후, 나는 시험을 실행할 것이라고 생각했다.
[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
곧장.