Get date of first day of week based on LocalDate.now() in Java 8

前端 未结 9 1493
梦谈多话
梦谈多话 2020-12-02 19:35

I would like the get the date of the first day of the week based on LocalDate.now(). The following was possible with JodaTime, but seems to be removed from the new Date API

相关标签:
9条回答
  • 2020-12-02 20:11

    Try

    System.out.println(now.with(DayOfWeek.MONDAY));
    
    0 讨论(0)
  • 2020-12-02 20:11

    With Joda Time, what do you think of

    now.toString("EEEE", locale)
    
    0 讨论(0)
  • 2020-12-02 20:12

    Despite all the previous answers, I still had to dig around to work out what Java8 was doing, so here is what I found to be the most intuitive way of doing it:

    LocalDate implements Temporal

    with(TemporalField field, long newValue)

    Returns an object of the same type as this object with the specified field altered.

    So we have to tell it which date part of LocalDate we want to change (DAY_OF_WEEK) and change to what value.

    In case you had doubts that the days in the week might be counted from 0 to 6 or from 1 to 7:

        System.out.printf("first day of week (0 or 1) == %d \n",
                ChronoField.DAY_OF_WEEK.range().getMinimum());
    
    first day of week (0 or 1) == 1 
    

    I had to nail down what my JDK was providing for defaults - YMMV:

        System.out.printf("default zone offset==[%s]\n",
                ZoneId.systemDefault());
        System.out.printf("1st day of week==%s\n",
                WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
    
    default zone offset==[Europe/London]
    1st day of week==MONDAY
    

    So if I execute some code based on these defaults, like so:

        LocalDate localDate = LocalDate.now();
        System.out.printf("localDate == %s \n", localDate);
        System.out.printf("localdate first day of week == %s (%s) \n",
                localDate.with(ChronoField.DAY_OF_WEEK, 1),
                localDate.with(ChronoField.DAY_OF_WEEK, 1).getDayOfWeek());
    
    localDate == 2017-10-24 
    localdate first day of week == 2017-10-23 (MONDAY) 
    

    then Java goes with ChronoField.DAY_OF_WEEK which not only defines which part of the date we want to alter, but also how to alter it.

    So if we want our code to deal with whatever the user specifies as the first day of the week, we create our own definition of how week-based calculations are meant to be done, using the WeekFields.of() factory method.

    Using this we can pass in our own dayOfWeek parameter to with() to do the date calculation the way we want:

        TemporalField myWeek = WeekFields.of(DayOfWeek.SUNDAY, 1).dayOfWeek();
        System.out.printf("configured localdate first day of week == %s (%s) \n",
                localDate.with(myWeek, 1),
                localDate.with(myWeek, 1).getDayOfWeek());
    
    configured localdate first day of week == 2017-10-22 (SUNDAY) 
    

    For more insight, have a look at the code in LocalDate.with(), it's quite interesting.

    0 讨论(0)
  • 2020-12-02 20:21

    As the correct Answer by Ray says, you can call with and pass the DayOfWeek enum.

    Time zone

    Note that time zone is crucial in determining the date of "today". At any moment the date varies by where you are standing on the globe.

    ZoneId zoneId = ZoneId.of ( "America/Montreal" );
    LocalDate firstDayOfThisWeek = LocalDate.now ( zoneId ).with ( DayOfWeek.MONDAY );
    

    If you do not specify a time zone, the JVM’s current default time zone is silently applied. Beware: That default can change at any moment during runtime! Better to specify your desired/expected time zone.

    ZonedDateTime

    You can apply a time zone (a ZoneId) to your LocalDate to get a ZonedDateTime representing the first moment of the week.

    ZonedDateTime thisWeekStart = firstDayOfThisWeek.atStartOfDay ( zoneId );
    
    0 讨论(0)
  • 2020-12-02 20:25

    Thanks to come from in this question.

    Calendar cal = Calendar.getInstance();
            cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day !
            cal.clear(Calendar.MINUTE);
            cal.clear(Calendar.SECOND);
            cal.clear(Calendar.MILLISECOND);
    
            // get start of this week in milliseconds
            cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
            System.out.println("Start of this week:       " + cal.getTime());
            System.out.println("... in milliseconds:      " + cal.getTimeInMillis());
    
    0 讨论(0)
  • 2020-12-02 20:29

    Note that the expression System.out.println(now.with(DayOfWeek.MONDAY)) is locale-independent as it uses ISO-8601, therefore it always jumps backwards to last Monday (or stays on Monday in case date points to Monday already).

    As such in US or some other countries - where week starts on Sunday - it may not work as you would expect - now.with(DayOfWeek.MONDAY) will not jump forward to Monday, in case date points to Sunday.

    In case you need to address these concerns, it is better to use the localized field WeekFields.dayOfWeek():

    LocalDate now = LocalDate.now();
    TemporalField fieldISO = WeekFields.of(Locale.FRANCE).dayOfWeek();
    System.out.println(now.with(fieldISO, 1)); // 2015-02-09 (Monday)
    
    TemporalField fieldUS = WeekFields.of(Locale.US).dayOfWeek();
    System.out.println(now.with(fieldUS, 1)); // 2015-02-08 (Sunday)
    

    Another example due to comments below:

    LocalDate ld = LocalDate.of(2017, 8, 18); // Friday as original date
    
    System.out.println(
        ld.with(DayOfWeek.SUNDAY)); // 2017-08-20 (2 days later according to ISO)
    
    // Now let's again set the date to Sunday, but this time in a localized way...
    // the method dayOfWeek() uses localized numbering (Sunday = 1 in US and = 7 in France)
    
    System.out.println(ld.with(WeekFields.of(Locale.US).dayOfWeek(), 1L)); // 2017-08-13
    System.out.println(ld.with(WeekFields.of(Locale.FRANCE).dayOfWeek(), 7L)); // 2017-08-20
    

    The US-example makes pretty clear that someone residing in US would expect to go to last and not to next Sunday because Sunday is considered as first day of week in US. The simple ISO-based expression with(DayOfWeek.SUNDAY) ignores this localization issue.

    0 讨论(0)
提交回复
热议问题