2016-05-12 73 views
4

我需要找到的最後一個星期使用Java 8日期和時間API(java.time)一年的第一天終於來到了此解決方案:年上週查找與java.time

LocalDate date = LocalDate.of(2016, 2, 17); 
LocalDate lastWeekOfYear = LocalDate.of(date.getYear() + 1, 1, 7) 
    .with(WeekFields.ISO.weekOfYear(), 1) 
    .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7); 

該解決方案找到下一年的第一週,必要時將星期幾調整爲星期一,並移回7天。有更聰明的方法來達到相同的結果嗎?

+2

看起來不錯給我,雖然我可能會使用'minusWeeks(1) ''而不是'minusDays(7)',並且放在一個新的行上,你可能會爲'lastWeekOfWeekYear'編寫自己的'TemporalAdjuster' –

+3

另一種方式(不一定更具可讀性)是'date.with(lastDayOfYear() ).minusDays(7 - WeekFields.ISO.getMinimalDaysInFirstWeek())。with(previousOrSame(MONDAY))' – assylias

+0

@Oxolotl我建議您提取您的建議解決方案,並將其作爲答案發布。您可以稍後接受它以標記問題as closed。完美的回答你自己的問題堆棧溢出 –

回答

3

正如所建議的那樣,我會自己回答這個問題(對評論進行小幅改進),因爲似乎沒有一個更簡單的解決方案。

LocalDate date = LocalDate.of(2016, 2, 17); 
LocalDate lastWeekOfYear = LocalDate.of(date.getYear() + 1, 1, 7) 
    .with(WeekFields.ISO.weekOfWeekBasedYear(), 1) 
    .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusWeeks(1); 
4

更新基於您的評論:

您可以從日起,得到了一年的最後一天回去,直到星期一。獲取WeekBasedYear這一結果並接受它,如果weekBasedYear是一樣的一天一年,otherways回到上週一和接受它的結果:

LocalDate day = LocalDate.of(2012, 2, 17); 
LocalDate result = day.with(TemporalAdjusters.lastDayOfYear()) 
          .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));  

//if day and result weekBasedYear are in the same weekYear then result else go back to previous Mondays 
result = result.get(WeekFields.ISO.weekBasedYear())== day.getYear()? result : 
       result.with(TemporalAdjusters.previous(DayOfWeek.MONDAY)); 

System.out.println(result); 

輸出:

2012-12-24 

希望這可以幫助。

+0

我認爲這個解決方案確實會在一年中的最後一天是星期一,星期二或星期三的情況下返回錯誤的結果。例如,2012年的最後一週從2012-12-24開始,而上面的代碼將返回2012-12-31。我應該在我的問題中指出,根據ISO 8601周的規定,我需要最後一週(請參閱[https://en.wikipedia.org/wiki/ISO_8601#Week_dates])。 – Oxolotl

+0

@Oxolotl是的,你當然應該定義你的條款,在這種情況下,你的意思是每年的一年。請修改您的問題,並加以澄清,而不是發表評論。 –

0

我認爲OP發現了最後的解決方案仍然不正確的,因爲我們在ISO週日期的情況下移動,而不是普通的日曆日期。因此,表達式LocalDate.of(date.getYear() + 1, 1, 7)在年邊界附近經常是錯誤的(參見示例方法lastWeekOfYearOld(...))。相反,我們必須添加一個以星期爲單位的年份,而不是一個日曆年(限於1月 - 12月),現在已經在第二個方法lastWeekOfYearCorrect(...)中使用了。我也顯示基礎上,周的年字段的上下文敏感值範圍另一個正確的選擇(參見方法lastWeekOfYearAlternative(...)

public static void main(String[] args) { 
    System.out.println(
       lastWeekOfYearOld(LocalDate.of(2015, 12, 31))); // 2015-12-28 (OK) 
    System.out.println(
       lastWeekOfYearOld(LocalDate.of(2016, 1, 1))); // 2016-12-26 (Wrong) 

    System.out.println(
       lastWeekOfYearCorrect(LocalDate.of(2015, 12, 31))); // 2015-12-28 (OK) 
    System.out.println(
       lastWeekOfYearCorrect(LocalDate.of(2016, 1, 1))); // 2015-12-28 (OK) 

    System.out.println(
       lastWeekOfYearAlternative(LocalDate.of(2015, 12, 31))); // 2015-12-28 (OK) 
    System.out.println(
       lastWeekOfYearAlternative(LocalDate.of(2016, 1, 1))); // 2015-12-28 (OK) 
} 

private static LocalDate lastWeekOfYearOld(LocalDate date) { 
    return LocalDate.of(date.getYear() + 1, 1, 7) 
     .with(WeekFields.ISO.weekOfWeekBasedYear(), 1) 
     .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusWeeks(1); 
} 

private static LocalDate lastWeekOfYearCorrect(LocalDate date) { 
    date = 
     date.plus(1, IsoFields.WEEK_BASED_YEARS) 
      .with(DayOfWeek.MONDAY) 
      .with(WeekFields.ISO.weekOfWeekBasedYear(), 1); 
    return date.minusWeeks(1); 
} 

private static LocalDate lastWeekOfYearAlternative(LocalDate date) { 
    TemporalField woyField = WeekFields.ISO.weekOfWeekBasedYear(); 
    date = date.with(woyField, woyField.rangeRefinedBy(date).getMaximum()); 
    return date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); 
} 
+0

上述解決方案對我而言並不像我們預期的那樣工作,但我理解您的觀點並認爲我的問題可能依然存在。我一直在尋找「2016年最後一週是什麼?」的解決方案。 - 傳遞的LocalDate的日期和月份組件因此是不相關的。如果我要求實現一個簽名爲'LocalDate lastWeekOfYear(int year)'的方法,這將更加清晰。 – Oxolotl