我们如何计算前一个星期日或之前的星期日或一般情况下如何在 n 周之前找出如何查找星期日?问题是,如果今天是星期天那么它应该今天作为星期日而不是上周返回。
寻找Joda-Time或Java 8时间解决方案。
修改 我试过了
DateTime sunday = now
.minusWeeks(1)
.withDayOfWeek(DateTimeConstants.SUNDAY)
.withTimeAtStartOfDay();
DateTime previousWeekSunday = now
.minusWeeks(2)
.withDayOfWeek(DateTimeConstants.SATURDAY)
.withTime(23, 59, 59, 999);
但如果当前是星期日,那么这个逻辑就会失败,因为它没有给出今天的日期。
答案 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方法将跳过对实际星期几的检查
LocalDate date = LocalDate.now();
LocalDate prevSun = date.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY));
prevSun = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
System.out.println(prevSun);
答案 1 :(得分:1)
这个问题已经用Java 8方法回答了,但仅仅是为了记录,这里是一个Joda-Time的解决方案(以及我对Java 8的2美分)。
如果我理解正确,上周日获得n th 的一般算法是:
n-1
周(因此对于n=1
,它会返回相同的日期)我创建了一个接收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 th (考虑到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中,您可以将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
时,您不需要每次调用它,只需将调整器存储在变量中并重复使用它:
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
没有日期字段,也无法了解工作日。