2 回答
TA贡献1801条经验 获得超16个赞
public static void numberOfWeeks(LocalDateTime startDateTime, LocalDateTime endDateTime) {
if (startDateTime.isAfter(endDateTime)) {
throw new IllegalArgumentException("End date must not be before start date");
}
LocalDate endDate = endDateTime.toLocalDate();
List<String> numberWeeks = new ArrayList<>();
LocalDate currentDate = startDateTime.toLocalDate();
while (currentDate.isBefore(endDate)) {
numberWeeks.add(formatWeek(currentDate));
currentDate = currentDate.plusWeeks(1);
}
// Now currentDate is on or after endDate, but are they in the same week?
if (currentDate.get(WeekFields.SUNDAY_START.weekOfWeekBasedYear())
== endDate.get(WeekFields.SUNDAY_START.weekOfWeekBasedYear())) {
numberWeeks.add(formatWeek(currentDate));
}
System.out.println(numberWeeks);
}
public static String formatWeek(LocalDate currentDate) {
return String.format("%d-W%d",
currentDate.get(WeekFields.SUNDAY_START.weekBasedYear()),
currentDate.get(WeekFields.SUNDAY_START.weekOfWeekBasedYear()));
}
使用上面的方法,您可以main从问题中打印出方法:
[2018-W34、2018-W35]
我看到您忽略了链接问题中的另一个答案,即YearWeek来自 ThreeTen Extra 库的答案。所以我假设你不想那样做。所以我使用LocalDate了几个星期。
虽然有几个用户未能重现您的确切问题,但我同意您在问题中的代码存在缺陷。
TA贡献1828条经验 获得超13个赞
LocalDateTime.parse( "2018-08-24T12:18:06,166".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.datesUntil(
LocalDateTime.parse( "2018-08-26T12:19:06,188".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.plusWeeks( 1 )
,
Period.ofWeeks( 1 )
)
.map( localDate -> localDate.get( WeekFields.SUNDAY_START.weekOfWeekBasedYear() ) )
.collect( Collectors.toList() )
.toString()
[34, 35]
流
让我们采用 Ole VVWeekFields在正确答案中显示的想法,但使用 Java Stream 技术缩短代码。虽然有趣,但我不一定推荐这种方法。
首先解析您的输入字符串以获取LocalDate对象。该LocalDate级表示没有时间一天和不同时区的日期,唯一的价值。
不幸的是,java.time类不支持逗号作为小数秒分隔符,而是期望一个句点(FULL STOP)。这与ISO 8601标准相反,该标准允许并且实际上更喜欢逗号。这是我在其他优秀的java.time类中发现的少数缺陷之一,大概是由于来自美国的程序员的偏见。为了解决这个缺陷,我们用一个 FULL STOP 代替逗号。
LocalDate inputDateStart =
LocalDateTime.parse(
"2018-08-24T12:18:06,166".replace( "," , "." ) // Unfortunately, the *java.time* classes fail to support the comma and instead only period. This runs contrary to the ISO 8601 standard which allows both and prefers comma.
)
.toLocalDate()
;
LocalDate inputDateStop =
LocalDateTime.parse(
"2018-08-26T12:19:06,188".replace( "," , "." )
)
.toLocalDate()
;
您希望使用定义为从星期日开始的周。因此,将您输入的日期调整为该日期当天或之前的星期日。
请注意,我们在此处添加了一个星期以适应问题的需要。更常见的是,我们不会做这个加法,遵循半开方法来定义一个时间跨度,其中开始是包含而结束是不包括的。与半开放相反,问题显然需要完全封闭的方法,其中开头和结尾都包含在内(我不建议这样做)。
LocalDate start = inputDateStart.with(
TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY )
);
LocalDate stop = inputDateStop.with(
TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY )
)
.plusWeeks( 1 ) // Add one to suit the Question, whereas commonly in date-time work we would have used Half-Open logic.
;
将一系列日期定义为Stream< LocalDate >. 我们通过一周的 a 一次跳跃Period一周。
Stream< LocalDate > stream =
startDate
.datesUntil(
stopDate ,
Period.ofWeeks( 1 )
)
;
如果需要,您可以通过将这些日期从流中收集到列表中来查看这些日期。但请注意,这会耗尽流。您需要重新建立流以继续我们的代码。
List< LocalDate > dates = stream.collect( Collectors.toList() );
System.out.println( dates );
[2018-08-19, 2018-08-26]
在流中运行该系列日期。在每个LocalDate对象上,获取周数。收集每个返回的周数作为一个Integer对象,所有收集在一个List.
List< Integer > weekNumbers =
stream
.map(
localDate -> localDate.get( WeekFields.SUNDAY_START.weekOfWeekBasedYear() )
)
.collect( Collectors.toList() )
;
转储到控制台。
System.out.println( weekNumbers );
[34, 35]
单线
如果你真的想为简洁而疯狂,我们可以在一行代码中完成所有这些。我不推荐这个,但尝试很有趣。
System.out.println(
LocalDateTime.parse( "2018-08-24T12:18:06,166".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.datesUntil(
LocalDateTime.parse( "2018-08-26T12:19:06,188".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.plusWeeks( 1 )
,
Period.ofWeeks( 1 )
)
.map( localDate -> localDate.get( WeekFields.SUNDAY_START.weekOfWeekBasedYear() ) )
.collect( Collectors.toList() )
);
[34, 35]
添加回答
举报