的問題已經與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.LocalDate
或org.joda.time.LocalDateTime
(該算法是一樣的,只是改變的方法變量的類型)。
的Java 8的方法(我的2美分)
在Java 8,你可以使用TemporalAdjuster
爲already 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
沒有日期字段,無法瞭解週一至週五。
我建議先閱讀https://docs.oracle.com/javase/tutorial/datetime/上的教程,然後展示您的嘗試。 –
似乎你應該更喜歡Java 8而不是Joda-Time。 [Joda-Time主頁](http://www.joda.org/joda-time/)說:「現在要求用戶遷移到java.time(JSR-310)。」 –
你的搜索和研究是什麼培養?你已經嘗試過什麼(以什麼方式失敗)? –