문제

날짜 범위가 주어지면 월요일 (또는 화요일, 수요일 등)이 그 범위에 있는지 알아야합니다.

현재 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 곧장.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top