我的意图是获取两个日期范围之间的星期数。第24周的日期为第24周,第35周的日期为第26周。现在的问题是,如果我将2018-08-22T12:18:06,166
作为开始日期,我将得到34,35,36。我不希望在这里看到36,因为结束日期不会在36周内。任何人都可以帮助我。这个问题与此处Week numbers from start date to end date Java提供的解决方案不同。解决方案存在我最近检测到的问题
下面是获取它的代码:
public static void main(String[] args) {
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss','SSS");
LocalDateTime startDate = LocalDateTime.parse("2018-08-24T12:18:06,166", format);
LocalDateTime endDate = LocalDateTime.parse("2018-08-26T12:19:06,188", format);
numberOfWeeks(startDate, endDate);
}
public static void numberOfWeeks(LocalDateTime startDate, LocalDateTime endDate) {
int addWeek = 0;
TemporalField tf = WeekFields.SUNDAY_START.weekOfYear();
if (startDate.get(tf) < endDate.get(tf)) {
addWeek = 1;
}
long weeks = WEEKS.between(startDate, endDate) + addWeek;
List<String> numberWeeks = new ArrayList<>();
if (weeks >= 0) {
int week = 0;
do {
//Get the number of week
LocalDateTime dt = startDate.plusWeeks(week);
int weekNumber = dt.get(tf);
numberWeeks.add(String.format("%d-W%d", dt.getYear(), weekNumber));
week++;
} while (week <= weeks);
}
System.out.println(numberWeeks);
}
答案 0 :(得分:4)
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]
我看到您已忽略链接问题中的the other answer,该问题使用了ThreeTen Extra库中的YearWeek
。所以我以为你不想那样做。所以我连续几周都在使用LocalDate
。
虽然有几个用户未能重现您的确切问题,但我确实同意问题中的代码存在缺陷。
答案 1 :(得分:3)
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]
让我们采用correct Answer by Ole V.V.中显示的WeekFields
的想法,但是使用Java Stream技术来缩短代码。尽管很有趣,但我不一定推荐这种方法。
首先解析您的输入字符串以获取LocalDate
对象。 LocalDate
类表示没有日期和时区的仅日期值。
不幸的是, java.time 类无法将逗号作为小数秒定界符来支持,而是期望使用句点(FULL STOP)。这与ISO 8601标准相反,该标准同时允许和实际上 prefers 逗号。这是我在本来很好的 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 >
。通过一周的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]