2017-06-02 46 views
3

我們如何計算前一個星期日或前一個星期日或一般情況下可以說如何在n周之前找出星期天?如果今天是星期天,那麼它應該是今天迴歸,而不是上週。如何在Java日期時間API或Joda時間查找第n個星期天?

尋找Joda-Time或Java 8時間解決方案。

編輯: 我試圖

DateTime sunday = now 
    .minusWeeks(1) 
    .withDayOfWeek(DateTimeConstants.SUNDAY) 
    .wi‌​thTimeAtStartOfDay()‌​; 
DateTime previousWeekSunday = now 
    .minusWeeks(2) 
    .withDayOfWeek(DateTimeConstants.SATURDAY) 
    .‌​withTime(23, 59, 59, 999); 

但如果當前是星期天那麼這個邏輯失敗,因爲它不會給今天的日期。

+3

我建議先閱讀https://docs.oracle.com/javase/tutorial/datetime/上的教程,然後展示您的嘗試。 –

+1

似乎你應該更喜歡Java 8而不是Joda-Time。 [Joda-Time主頁](http://www.joda.org/joda-time/)說:「現在要求用戶遷移到java.time(JSR-310)。」 –

+0

你的搜索和研究是什麼培養?你已經嘗試過什麼(以什麼方式失敗)? –

回答

4

你基本上需要檢查,如果今天是星期天,如果沒有,那麼回頭的前一...(或遞歸如果你需要前一到回遷日期...)

用java 8你將需要:


LocalDate date = LocalDate.now(); 
DayOfWeek todayAsDayOfWeek = date.getDayOfWeek(); 
LocalDate prevSun = todayAsDayOfWeek == DayOfWeek.SUNDAY ? date : date.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY)); 
System.out.println(prevSun); 

編輯:previousOrSame方法將跳過實際的檢查dayof一週

LocalDate date = LocalDate.now(); 
    LocalDate prevSun = date.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY)); 

    prevSun = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY)); 
    System.out.println(prevSun); 
+3

'TemporalAdjuster'的'PreviousOrSame'一步完成同樣的事情。 – Magnus

+1

在找到前一個星期日(或今天如果星期天)後,您可以使用'prevSun.minusWeeks(n)'向後計算* n *星期日。 –

+1

儘管如此,這個細節可能會有所作爲:我傾向於將一個參數傳遞給'LocalDate.now()'以使時區顯式化。即使在你通過'ZoneId.systemDefault()'的情況下。這樣,你告訴讀者 - 你自己 - 你已經考慮過時區並決定你想要哪一個。 –

1

的問題已經與Java 8辦法回答,只是備案,這是Joda-Time的解決方案(也是我的2美分Java 8)。

如果我理解正確的話,一般的算法得到第n 一個星期日是:

  • 如果當前日期已經是一個星期天,回去n-1周(所以n=1,它返回同日)
  • 否則,從

我已經創建了一個接收方法日期找了N個以前週日n(週數)和DateTime(開始日期)。代碼是:

// get the n'th previous Sunday, from the given DateTime 
public DateTime nPreviousSunday(int n, DateTime dateTime) { 
    // avoid zero or negative numbers (optional, see if it fits your use cases) 
    if (n <= 0) { 
     return dateTime; // return the same date 
    } 

    DateTime d = dateTime; 

    // get first previous (or same) Sunday 
    int dow = d.getDayOfWeek(); 
    if (dow != DateTimeConstants.SUNDAY) { // not a Sunday, adjust the day to the previous one 
     int diff = DateTimeConstants.SUNDAY - dow; 
     // DateTimeConstants.SUNDAY is 7, so diff is always positive 
     // d is (7 - diff) days ahead of Sunday, adjusting 
     d = d.minusDays(7 - diff); 
    } 

    // find the n'th previous (considering that the first was already found above) 
    d = d.minusWeeks(n - 1); 

    return d; 
} 

以下是04/06/2017(星期日)的測試。對於n=1,它返回04/06/2017,並n >= 2從該日起發現第n 一個星期日(考慮到04/06/2017本身是第一個):

System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 4, 10, 0))); // 2017-06-04 
System.out.println(nPreviousSunday(2, new DateTime(2017, 6, 4, 10, 0))); // 2017-05-28 
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 4, 10, 0))); // 2017-05-21 

測試對於05/06/2017(不是星期日),它得到相同的結果(如第一個星期日是04/06/2017):

System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 5, 10, 0))); // 2017-06-04 
System.out.println(nPreviousSunday(2, new DateTime(2017, 6, 5, 10, 0))); // 2017-05-28 
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 5, 10, 0))); // 2017-05-21 

測試了整整一個星期,直到週六(10/06/2017):

System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 6, 10, 0))); // 2017-06-04 
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 7, 10, 0))); // 2017-06-04 
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 8, 10, 0))); // 2017-06-04 
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 9, 10, 0))); // 2017-06-04 
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 10, 10, 0))); // 2017-06-04 

System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 6, 10, 0))); // 2017-05-21 
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 7, 10, 0))); // 2017-05-21 
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 8, 10, 0))); // 2017-05-21 
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 9, 10, 0))); // 2017-05-21 
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 10, 10, 0))); // 2017-05-21 

PS:我使用的是DateTime,但你也可以使用此代碼爲org.joda.time.LocalDateorg.joda.time.LocalDateTime(該算法是一樣的,只是改變的方法變量的類型)。


的Java 8的方法(我的2美分)

在Java 8,你可以使用TemporalAdjusteralready answered。但是,僅僅把我的2美分,你可以創建一個返回TemporalAdjuster的方法,然後你可以與任何Java的時間類型的使用它:

// get the n'th previous dayOfWeek, from the given temporal 
public TemporalAdjuster previous(int n, DayOfWeek dayOfWeek) { 
    return (temporal) -> { 
     // avoid zero or negative numbers (optional, see if it fits your use cases) 
     if (n <= 0) { 
      return temporal; // return the same temporal 
     } 

     // get first previous (or same) dayOfWeek 
     Temporal t = temporal.with(TemporalAdjusters.previousOrSame(dayOfWeek)); 

     // find the n'th previous (considering that the first was already found above) 
     t = t.minus(n - 1, ChronoUnit.WEEKS); 

     return t; 
    }; 
} 

所以,你可以使用這種方式:

System.out.println(LocalDate.of(2017, 6, 4).with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04 
System.out.println(LocalDate.of(2017, 6, 4).with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28 
System.out.println(LocalDate.of(2017, 6, 4).with(previous(3, DayOfWeek.SUNDAY))); // 2017-05-21 

System.out.println(LocalDate.of(2017, 6, 5).with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04 
System.out.println(LocalDate.of(2017, 6, 5).with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28 
System.out.println(LocalDate.of(2017, 6, 5).with(previous(3, DayOfWeek.SUNDAY))); // 2017-05-21 

的好處是,它也可以與其他類型:

LocalDateTime dt = LocalDateTime.of(2017, 6, 4, 10, 0); 
System.out.println(dt.with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04T10:00 
System.out.println(dt.with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28T10:00 

ZonedDateTime zdt = ZonedDateTime.of(dt, ZoneId.of("America/Sao_Paulo")); 
System.out.println(zdt.with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04T10:00-03:00[America/Sao_Paulo] 
System.out.println(zdt.with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28T10:00-03:00[America/Sao_Paulo] 

OffsetDateTime odt = OffsetDateTime.of(dt, ZoneOffset.ofHours(2)); 
System.out.println(odt.with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04T10:00+02:00 
System.out.println(odt.with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28T10:00+02:00 

由於previous()方法返回一個TemporalAdjuster,你不需要調用它每一次,沮ST存儲調節的變量,並重復使用它:

TemporalAdjuster thirdPreviousSunday = previous(3, DayOfWeek.SUNDAY); 
System.out.println(LocalDate.of(2017, 6, 4).with(thirdPreviousSunday)); // 2017-05-21 
System.out.println(LocalDate.of(2017, 6, 5).with(thirdPreviousSunday)); // 2017-05-21 

這種方法的另一個優點是:代碼變得更清晰和乾淨(IMO),並將其與每週的任何一天的工作。


PS:下面的代碼拋出異常,如果類型不具有DayOfWeek字段(如LocalTime,僅具有小時/分鐘/秒/納秒):

// throws UnsupportedTemporalTypeException (because LocalTime doesn't have the DayOfWeek field) 
LocalTime.now().with(previous(1, DayOfWeek.SUNDAY)); 

只是提醒的是,它已經與現有的調節情況:

// also throws exception (Unsupported field: DayOfWeek) 
LocalTime.now().with(TemporalAdjusters.previous(DayOfWeek.SUNDAY)); 

這是有道理的,因爲LocalTime沒有日期字段,無法瞭解週一至週五。

相關問題