简体   繁体   中英

How to get the start and end of a calendar week as LocalDateTime (java 8)

I want to transform the following String:

private String cw = "35/19" 

into 2 dates.

The start date can be formatted with:

private final DateTimeFormatter startOfWeekFormat = new DateTimeFormatterBuilder()
   .appendPattern("ww/YY")
   .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
   .toFormatter();

which when called returns: 26.08.2019

LocalDate.parse(cw, startOfWeekFormat).atStartOfDay();

But I struggle with the end of the week which is basically the start of the next week "36/19".

I tried to add plus 8 days, but that throws an exception:

private final DateTimeFormatter endOfWeekFormat = new DateTimeFormatterBuilder()
    .appendPattern("ww/YY")
    .parseDefaulting(WeekFields.ISO.dayOfWeek(), 8)
    .toFormatter();
LocalDateTime ldt=LocalDate.parse(cw, startOfWeekFormat)
                    .atStartOfDay()
                    .with(TemporalAdjusters.next(DayOfWeek.MONDAY));

Demo:

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;

public class Main {
    public static void main(String[] args) {
        String cw = "35/19";
        final DateTimeFormatter startOfWeekFormat = new DateTimeFormatterBuilder()
                                            .appendPattern("ww/YY")
                                            .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
                                            .toFormatter();
        
        LocalDateTime ldt=LocalDate.parse(cw, startOfWeekFormat)
                            .atStartOfDay()
                            .with(TemporalAdjusters.next(DayOfWeek.MONDAY));
        System.out.println(ldt);
    }
}

Output:

2019-09-02T00:00

Another answer that adds a week, but in a different way:

I assume you always want the start date and the end date of a calendar week. You could write a method that returns a Map.Entry<LocalDate, LocalDate> where the key is the start date and the value is the end date.

It could look like this:

public static Map.Entry<LocalDate, LocalDate> getStartAndEndOfCalendarWeek(String calendarWeek) {
    DateTimeFormatter startOfWeekFormatter = new DateTimeFormatterBuilder()
            .appendPattern("ww/YY")
            .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
            .toFormatter();
    
    LocalDate weekStart = LocalDate.parse(calendarWeek, startOfWeekFormatter);
    LocalDate weekEnd = weekStart.plusWeeks(1);

    return new AbstractMap.SimpleEntry<LocalDate, LocalDate>(weekStart, weekEnd);
}

Printing the result in a main with your example String like this

public static void main(String[] args) {
    String cw = "35/19";
    Map.Entry<LocalDate, LocalDate> calendarWeekStartAndEndDate
                                    = getStartAndEndOfCalendarWeek(cw);
    System.out.println(calendarWeekStartAndEndDate.getKey() 
            + " - " + calendarWeekStartAndEndDate.getValue());
}

would output

2019-08-26 - 2019-09-02

I know this adds a week to the result of using your DateTimeFormatter to parse the String , but I don't think involving two different parsers or parsing actions would cause any benefit over adding a week.

If you want the starts of two consecutive calendar weeks, the make the addition add an additional day , like this:

LocalDate weekEnd = weekStart.plusWeeks(1).plusDays(1);

and if you want a LocalDateTime (which is not quite clear to me if you really do), you could of course adjust the return type and use .atStartOfDay() when you parse the weekStart , the addition would stay the same.

I'd prefer an solution where I don't need to add the additional days to the result of the parsed string. Like a solution where the "plus(8)" is already included in the formatter.

That is not possible. You can't parse 2020-08-30 into 2020-08-31 or 2020-09-30. Just as well you cannot parse 35/19 into a date in week 36 of 2019.

I'm all in favour of half-open intervals, so I do see that it would be practical in your situation. Sorry that it isn't possible.

Link: Half-Open Interval in WolframMathWorld.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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