繁体   English   中英

Java中两个日期之间的星期数

[英]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

尽管有几个用户无法重现您的确切问题,但我确实同意问题中的代码存在缺陷。

tl; dr

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM