9

I have the week number, its curresponding year and dayOfWeek number(i.e. 1 for Monday, 2 for Tuesday and so on). Is there a way to find the date with this information in java?

Following is a method I found online.

int week = 51;
LocalDate wkstart = LocalDate.now().with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, week);
LocalDate mon = wks.plusDays(1);
LocalDate tue = wks.plusDays(2);
LocalDate wed = wks.plusDays(3);
LocalDate thu = wks.plusDays(4);
LocalDate fri = wks.plusDays(5);
LocalDate sat = wks.plusDays(6);
LocalDate wkend = wks.plusDays(7);

But then realised that wkstart is storing the current date instead of the start of the week.
Is there a better way of doing this?

Ebenezer Isaac
  • 772
  • 1
  • 8
  • 31

3 Answers3

10

Instead of adding a number of days to wkstart, use with again to set the day of week. For example:

LocalDate date = LocalDate.now()
    .with(WeekFields.ISO.weekBasedYear(), 2018) // year
    .with(WeekFields.ISO.weekOfWeekBasedYear(), 51) // week of year
    .with(WeekFields.ISO.dayOfWeek(), DayOfWeek.MONDAY.getValue()); // day of week
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • @OleV.V. You're right. Why not `WeekFields.ISO.weekBasedYear()` just to be consistent with the other fields though? There seems to be very little difference between the two... (I chose `WeekFields.ISO` because I don't like to see caps all over the place) – Sweeper Dec 18 '19 at 06:11
  • I don’t like any shouting in my code either. :-) Also `WeekFields.ISO` lends itself better to modification in case someone wants to define weeks differently. – Ole V.V. Dec 18 '19 at 06:16
8

tl;dr

LocalDate localDate = 
        YearWeek               // Represent an entire week of a week-based year per the ISO 8601 standard definition of a week.
        .of(                   // Instantiate a `YearWeek` object.
            2019 ,             // Specify the week-based year number, NOT the calendar year.
            51                 // Specify the week number, 1-52 or 1-53. 
        )
        .atDay(
            DayOfWeek.of( 1 )  // The value 1 yields a `DayOfWeek.MONDAY` object.
        )
;

org.threeten.extra.YearWeek

The Answer by Sweeper looks correct. But there is a more specialized class for this.

If doing much work with weeks of week-based years per the ISO 8601 definition of week, use the YearWeek class found in the ThreeTen-Extra library. This library adds extra functionality to the java.time classes built into Java 8 and later.

Determine the week.

YearWeek yearWeek = YearWeek.of( 2019 , 51 ) ;

Get a LocalDate for the day-of-week within that week.

LocalDate localDate = yearWeek.atDay( DayOfWeek.MONDAY ) ;

For the day-of-week, you should be using DayOfWeek enum objects in your code rather than mere integer numbers. To get a DayOfWeek from an original number 1-7 for Monday-Sunday, call DayOfWeek.of( x ).

DayOfWeek dow = DayOfWeek.of( 1 ) ;  // 1 = Monday, 7 = Sunday.

Putting that all together we get this one-liner.

LocalDate localDate = YearWeek.of( 2019 , 51 ).atDay( DayOfWeek.of( 1 ) ) ;
 

To be clear… The ISO 8601 definition of a week is:

  • Week # 1 contains the first Thursday of the year.
  • Weeks start on a Monday, ending on a Sunday.
  • A year has either 52 or 53 complete 7-day weeks.
  • The first/last weeks of the week-based year may contain the trailing/leading days of the previous/next calendar years. Thus, the calendar year of those days differ from the week-based year.
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

It also depends on the Locale.

Note that the first day of the week is Locale-dependent e.g. it is Monday in the UK while Sunday in the US. As per the ISO 8601 standards, it is Monday. For comparison, check the US calendar and the UK calendar. Accordingly, the date will vary as shown in the example below:

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Test
        int weekNumber = 34;
        int year = 2021;
        
        System.out.println(getLocalDate(weekNumber, DayOfWeek.TUESDAY, year, Locale.UK));
        System.out.println(getLocalDate(weekNumber, DayOfWeek.TUESDAY, year, Locale.US));
        
        System.out.println(getLocalDate(weekNumber, DayOfWeek.SUNDAY, year, Locale.UK));
        System.out.println(getLocalDate(weekNumber, DayOfWeek.SUNDAY, year, Locale.US));        
    }

    static LocalDate getLocalDate(int weekNumber, DayOfWeek dow, int year, Locale locale) {
        return LocalDate.of(year, 2, 1)
                .with(dow)
                .with(WeekFields.of(locale).weekOfWeekBasedYear(), weekNumber);
    }
}

Output:

2021-08-24
2021-08-17
2021-08-29
2021-08-15

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110