[英]Week numbers between two dates in Java
我的意图是使两个日期范围之间的星期数。 日期第24周的第24个秋天,日期第35周的第26个秋天。现在的问题是,如果我将2018-08-22T12:18:06,166
作为开始日期,我会得到34,35,36。 我不希望在这里看到36,因为结束日期不会在36周内。任何人都可以帮助我。 这个问题与此处提供的解决方案不同: 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);
}
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]
我看到您忽略了链接问题中的另一个答案 ,一个使用ThreeTen Extra库中的YearWeek
的答案。 所以我以为你不想那样做。 所以我几个星期都在使用LocalDate
。
尽管有几个用户无法重现您的确切问题,但我确实同意问题中的代码存在缺陷。
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 VV在正确的Answer中显示的WeekFields
的想法,但是使用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 >
。 通过一个星期的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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.