2008-11-13 50 views
17

Đây là những gì tôi đang cố gắng làm: Cho một ngày, một ngày trong tuần và một số nguyên n, xác định xem ngày có là ngày n thứ thứ trong tháng hay không.Làm cách nào để xác định xem một ngày cụ thể có phải là ngày trong tuần thứ N của tháng không?

Ví dụ:

  • đầu vào của 1/1/2009,Monday,2 sẽ là sai vì 1/1/2009 không phải là thứ Hai thứ hai

  • đầu vào của 11/13/2008,Thursday,2 sẽ trở thành sự thật vì nó là lần thứ hai Thứ năm

Làm cách nào để cải thiện việc triển khai này?

private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n) 
{ 
    int d = date.Day; 
    return date.DayOfWeek == dow && (d/ 7 == n || (d/ 7 == (n - 1) && d % 7 > 0)); 
} 

Trả lời

12

Bạn có thể thay đổi việc kiểm tra trong tuần để các chức năng sẽ đọc:

private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n){ 
    int d = date.Day; 
    return date.DayOfWeek == dow && (d-1)/7 == (n-1); 
} 

Khác hơn thế, nó trông khá tốt và hiệu quả.

1

Here là những gì MSDN phải nói. VB của nó, nhưng nó dịch dễ dàng.

+0

mà kinda không đối diện với những gì tôi muốn – Kevin

8

Câu trả lời là từ this website. Sao chép/dán vào đây trong trường hợp trang web đó bị mất.

public static DateTime FindTheNthSpecificWeekday(int year, int month,int nth, System.DayOfWeek day_of_the_week) 
{ 
    // validate month value 
    if(month < 1 || month > 12) 
    { 
     throw new ArgumentOutOfRangeException("Invalid month value."); 
    } 

    // validate the nth value 
    if(nth < 0 || nth > 5) 
    { 
     throw new ArgumentOutOfRangeException("Invalid nth value."); 
    } 

    // start from the first day of the month 
    DateTime dt = new DateTime(year, month, 1); 

    // loop until we find our first match day of the week 
    while(dt.DayOfWeek != day_of_the_week) 
    { 
     dt = dt.AddDays(1); 
    } 

    if(dt.Month != month) 
    { 
     // we skip to the next month, we throw an exception 
     throw new ArgumentOutOfRangeException(string.Format("The given month has less than {0} {1}s", nth, day_of_the_week)); 
    } 

    // Complete the gap to the nth week 
    dt = dt.AddDays((nth - 1) * 7); 

    return dt; 
} 
+0

điều này cũng trái ngược với những gì tôi muốn – Kevin

+0

Cho dù đó là chính xác những gì Kevin cần, điều này rất nhiều những gì tôi cần. Cảm ơn bạn đã đăng nó. –

+0

kiểm tra cho tháng hợp lệ nên được thực hiện sau khi ngày được thêm vào. if (dt.Month! = month) luôn đúng sau ngày đầu tiên của tháng được tìm thấy – SQueek

1

Dường như ngôn ngữ cung cấp phương pháp ngày/ngày cho một ngày nhất định. Nếu có ai quan tâm, bạn có thể đọc về Zeller's congruence.

Tôi không nghĩ đó là điều họ muốn bạn làm nhưng bạn có thể tìm thấy ngày trong tuần của ngày đầu tiên của tháng đó. Bây giờ tôi nghĩ về nó, bạn có thể tìm thấy ngày trong tuần cho ngày nhất định là N và nhận được điều đó modulo 7.

Ồ chờ đợi, đó là lần thứ N xảy ra trong một ngày trong tuần (như Chủ Nhật) hay giống như Nth ngày trong tuần của tháng! Được rồi, tôi thấy các ví dụ.

Có lẽ nó sẽ làm cho một sự khác biệt nếu bạn có thể xây dựng một ngày như ngày 1 tháng ..

Cho rằng đó là sự xuất hiện thứ N của một ngày trong tuần, và rằng bạn không thể fiddle với datatype datetime bất cứ điều gì, và rằng bạn có quyền truy cập vào cả một ngày nhận được trong tuần và nhận được ngày của tháng chức năng. Chủ nhật sẽ là số không?

1) Trước tiên, ngày trong tuần sẽ phải khớp với ngày trong tuần nhất định.
2) N phải có ít nhất 1 và tối đa 4.
3) Ngày trong tháng sẽ nằm trong khoảng từ n * 7 * dayOfWeek + 1 và n * 7 * dayOfWeek + 6 cho cùng n.
- Hãy để tôi suy nghĩ về điều đó. Nếu chủ nhật là ngày đầu tiên .. 0 * 7 * 0 + 1 = 1 và thứ bảy thứ 6 sẽ là 0 * 7 * 0 + 6.

Suy nghĩ 1 và 3 ở trên là đủ vì chức năng nhận ngày tháng không được vi phạm 2.

(* first try, this code sucks *) 

function isNthGivenDayInMonth(date : dateTime; 
           dow : dayOfWeek; 
           N : integer) : boolean; 
    var B, A : integer (* on or before and after day of month *) 
    var Day : integer (* day of month *) 
    begin 
    B := (N-1)*7 + 1; A := (N-1)*7 + 6; 
    D := getDayOfMonth(date); 
    if (dow <> getDayOfWeek(date) 
     then return(false) 
     else return((B <= Day) and (A >= Day)); 
    end; (* function *) 

Hy vọng không có lỗi trong đó!
[chỉnh sửa: Thứ bảy sẽ là ngày thứ 7 và phần trên phía trên (N-1)*7 + 7.]
Giải pháp của bạn có vẻ như sẽ khớp với 2 tuần khác nhau? Có vẻ như nó sẽ luôn trả về 0 cho Chủ nhật? Nên đã làm giả mã trong C# .. ngắn mạch & & là như tôi nếu .. hey không nên chủ nhật trận đấu đầu tiên cho N = 1 trong tháng bắt đầu vào chủ nhật?

d/ 7 == n 

Điều đó sẽ dẫn đến (either 0 or 1)/7 == 1, điều đó không thể đúng! || của bạn cũng bắt được số (n-1), Robert có điều đó. Đi với câu trả lời của Robert Wagner! Nó chỉ có 2 dòng, ngắn là tốt! Có (Day-1) mod 7
[chỉnh sửa: (Day-1) div 7] loại bỏ các biến không cần thiết của tôi và 2 dòng thiết lập.

Để ghi lại, điều này cần được kiểm tra cho các trường hợp ranh giới và cứ như thế nào nếu ngày 31 tháng 8 là Chủ Nhật hoặc Thứ Bảy.
[chỉnh sửa: Có nên đã kiểm tra trường hợp cuối tuần quá. ! Xin lỗi]

0

Trong this answer, đoạn code sau cần phải được lộn:

// Complete the gap to the nth week 
dt = dt.AddDays((nth - 1) * 7); 

if(dt.Month != month) 
{ 
// we skip to the next month, we throw an exception 
throw new ArgumentOutOfRangeException(”The given month has less than ” nth.ToString() ” ” 
day_of_the_week.ToString() “s”); 
} 
0

Hầu hết các câu trả lời trên là một phần chính xác hoặc không cần thiết phức tạp. Bạn có thể thử chức năng đơn giản này, cũng kiểm tra xem ngày đã cho là ngày cuối cùng nhưng thứ N của tháng.

public static bool IsNthDayofMonth(this DateTime date, DayOfWeek weekday, int N) 
    { 
     if (N > 0) 
     { 
      var first = new DateTime(date.Year, date.Month, 1); 
      return (date.Day - first.Day)/ 7 == N - 1 && date.DayOfWeek == weekday; 
     } 
     else 
     { 

      var last = new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1); 
      return (last.Day - date.Day)/7 == (Math.Abs(N) - 1) && date.DayOfWeek == weekday; 
     } 
0

Trong trường hợp bạn muốn có một danh sách các ngày trong một khoảng thời gian (không chỉ một) cho Nth dayOfWeek của một tháng, bạn có thể sử dụng này:

internal static List<DateTime> GetDatesForNthDOWOfMonth(int weekNum, DayOfWeek DOW, DateTime beginDate, DateTime endDate) 
{ 
    List<DateTime> datesForNthDOWOfMonth = new List<DateTime>(); 
    int earliestDayOfMonth = 1; 
    int latestDayOfMonth = 7; 
    DateTime currentDate = beginDate; 

    switch (weekNum) 
    { 
     case 1: 
      earliestDayOfMonth = 1; 
      latestDayOfMonth = 7; 
      break; 
     case 2: 
      earliestDayOfMonth = 8; 
      latestDayOfMonth = 14; 
      break; 
     case 3: 
      earliestDayOfMonth = 15; 
      latestDayOfMonth = 21; 
      break; 
     case 4: 
      earliestDayOfMonth = 22; 
      latestDayOfMonth = 28; 
      break; 
    } 

    while (currentDate < endDate) 
    { 
     DateTime dateToInc = currentDate; 
     DateTime endOfMonth = new DateTime(dateToInc.Year, dateToInc.Month, DateTime.DaysInMonth(dateToInc.Year, dateToInc.Month)); 
     bool dateFound = false; 
     while (!dateFound) 
     { 
      dateFound = dateToInc.DayOfWeek.Equals(DOW); 
      if (dateFound) 
      { 
       if ((dateToInc.Day >= earliestDayOfMonth) && 
        (dateToInc.Day <= latestDayOfMonth)) 
       { 
        datesForNthDOWOfMonth.Add(dateToInc); 
       } 
      } 
      if (dateToInc.Date.Equals(endOfMonth.Date)) continue; 
      dateToInc = dateToInc.AddDays(1); 
     } 
     currentDate = new DateTime(currentDate.Year, currentDate.Month, 1); 
     currentDate = currentDate.AddMonths(1); 
    } 
    return datesForNthDOWOfMonth; 
} 

... và cuộc gọi nó theo cách này:

// This is to get the 1st Monday in each month from today through one year from today 
DateTime beg = DateTime.Now; 
DateTime end = DateTime.Now.AddYears(1); 
List<DateTime> dates = GetDatesForNthDOWOfMonth(1, DayOfWeek.Monday, beg, end); 
// To see the list of dateTimes, for verification 
foreach (DateTime d in dates) 
{ 
    MessageBox.Show(string.Format("Found {0}", d.ToString())); 
} 

Bạn có thể nhận thứ Sáu thứ 2 của mỗi tháng như vậy:

List<DateTime> dates = GetDatesForNthDOWOfMonth(2, DayOfWeek.Friday, beg, end); 

... v.v.

Các vấn đề liên quan