为了账号安全,请及时绑定邮箱和手机立即绑定

Java中两个日期之间的周数

Java中两个日期之间的周数

杨魅力 2021-08-19 19:17:16
我的目的是获取两个日期范围之间的周数。日期 24 日落在第 34 周,第 262018-08-22T12:18:06,166日落在第 35 周。现在的问题是,如果我将其作为开始日期,我将得到 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);}
查看完整描述

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了几个星期。


虽然有几个用户未能重现您的确切问题,但我同意您在问题中的代码存在缺陷。


查看完整回答
反对 回复 2021-08-19
?
慕田峪7331174

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]


查看完整回答
反对 回复 2021-08-19
  • 2 回答
  • 0 关注
  • 477 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信