2012-11-12 254 views
1

最近我收到一封郵件,其中說,2012年12月是一個奇怪的月份。本月有五個星期六,五個星期五和五個星期一。另外它說這隻會在700年後發生一次。因此,我需要檢查在2000年到2100年之間,有多少個月將分別有五個星期六,星期日和星期一。Java日曆日期檢查

這可以通過Java(尤其是使用Calander API)來實現嗎?

任何有關示例代碼的想法都是可行的。

謝謝。

回答

6

對於任何月份有5日(週六,週日,週一),則必須:

  • 有31天(4個全周和三個額外的天)
  • 開始上週六(三天最後必須是第五個星期六,星期日,星期一)

即使是根本破壞的java.util.Calendar API,這兩種檢查都應該相當容易。 (首選Joda Time)。如果您在實施其中一項時遇到困難,您應該發佈特定問題,向我們展示到目前爲止您到底有多遠。

+0

有幾個月有5個星期六,少於31天。此外,星期六開始的規則也不是強制性的。看到我的答案。 – dan

+1

但是如果OP需要全部星期六......星期五五次,那麼規則是有效的。 – dan

1

請檢查下面的代碼:

/** 
* Print all the months which has five Mondays, Saturdays and Sundays 
* @param from year from 
* @param to year to 
*/ 
public void printMonths(int from, int to) { 
    List<String> monthList = new ArrayList<String>(); 
    for (int year =from; year<=to;year++) { 
     monthList.addAll(getMonth(year)); 
    } 

    for (String s : monthList) { 
     System.out.println(s); 
    } 
} 

/** 
* Get month with five sundays, saturdays and mondays 
* @param year 
* @return 
*/ 
private List<String> getMonth(int year) { 
    List<String> monthList = new ArrayList<String>(); 
    for (int month = 0; month < 12; month++) { 
     if (check(year, month)) { 
      monthList.add("" + year + "-" + (month+1)); 
     } 
    } 
    return monthList;  
} 

private boolean check(int year, int month) { 
    return checkFiveDays(year, month, 1) && checkFiveDays(year, month, 2) 
    && checkFiveDays(year, month, 7); 

} 

private boolean checkFiveDays(int year, int month, int dayOfWeek) { 
    Calendar c = Calendar.getInstance(); 
    c.set(year, month, 0, 0, 0, 0); 
    int times = 0; 
    do { 
     if (c.get(Calendar.DAY_OF_WEEK) == dayOfWeek) { 
      times++; 
     } 
     c.add(Calendar.DAY_OF_MONTH, 1); 
    } while (c.get(Calendar.MONTH)== month); 

    return times == 5; 
} 
-1

實際上一個月有5日(週六,週日或週一),這是沒有必要有31天,見2012年9月(甚至二月某些閏年像2020年可以有5個星期六)。 即使在這一天開始的月份,請參閱:2013年3月,星期六的情況。
使用喬達它的簡單計算所有這樣的情況下,2000年和2100之間,如:

DateTimeFormatter dateParser = DateTimeFormat.forPattern("yyyy");                
DateTime startDate = dateParser.parseDateTime("2000");                  
DateTime stopDate = dateParser.parseDateTime("2100");                   
DateTime date = startDate;                         
DateTime lastInMonth;                           
if (date.getDayOfWeek() != DateTimeConstants.SATURDAY)                  
    date = date.plusWeeks(1).withDayOfWeek(DateTimeConstants.SATURDAY);              
int count = 0;                            
while (date.isBefore(stopDate)) {                        
    if (date.getDayOfWeek() != DateTimeConstants.SATURDAY) //if it's not starting on Saturday         
     date = date.plusWeeks(1).withDayOfWeek(DateTimeConstants.SATURDAY); //jump to the first Saturday      
    lastInMonth = date.plusWeeks(4); //jump 4 weeks                   
    if (date.getMonthOfYear() == lastInMonth.plusDays(2).getMonthOfYear()) { //check if we are still on the same month  
     count++;                            
     // System.out.println("date = " + date); //uncomment to see each such month            
    }                               
    date = date.plusMonths(1); //advance a month                    
    date = date.withDayOfMonth(1); //start on the first day                 
}                                
System.out.println("Between " + startDate + " and " + stopDate + " there are " + count + " months that have five Saturdays"); 

once in some 700 years only這並不完全正確,即使我們只計算了月月。

+0

要有五個星期六*和*五個星期日*和*五個星期一,您絕對必須在該月有31天。這就是問題所要求的。你的代碼只顯示五個星期六的任何月份,這根本不是一回事。 –

+0

@JonSkeet因爲我使用了'date.getMonthOfYear()== lastInMonth.plusDays(2).getMonthOfYear()',它會檢查下個星期一在第五個星期六之後是否在同一個月。 – dan

+0

@JonSkeet最初我只計算星期五的情況,但在注意到用戶需要所有人都是五次的情況下,我更新了答案。如果你能在目前的實施中解釋我錯過了什麼,我將不勝感激。 – dan