Home > Enterprise >  How to get the first Sunday of the Month given week number and year?
How to get the first Sunday of the Month given week number and year?

Time:05-13

Given a week number and a year, I'd like to be able to compute the first Sunday of that month. I've cobbled together some code that "mostly", but not always, works. Not sure why it doesn't work for every example, but that's why I'm posting. :)

The code below should get the first Sunday of the year, then iterate the number of weeks (the week number) entered. When done, the code should print out that first Sunday's date.

When incorrect, the code prints the previous Sunday, not the apparently correct one.

Suggestions appreciated.

public static void main(String[] args) throws IOException, MessagingException
{
    int enteredWeekNumber = 18;
    int enteredYear = 2022;

    int doyCounter = 1;
    LocalDate firstDoy = LocalDate.of(enteredYear, Month.JANUARY, 1);
    LocalDate someSunday = firstDoy.with(firstInMonth(DayOfWeek.SUNDAY));

    // Loop to get every Sunday by adding Period.ofDays(7) the current Sunday.
    while (someSunday.getYear() == enteredYear && doyCounter <= enteredWeekNumber)
    {
        System.out.println(" *** "   someSunday.
                format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)));
        someSunday = someSunday.plus(Period.ofDays(7));
        doyCounter  ;
    }
}

CodePudding user response:

tl;dr

org.threeten.extra.YearWeek   // Represents a week-based year and week per the ISO 8601 definition.
.of( y , w )                  // Pass your week-based year number, and your week (0-52, 0-53). 
.atDay( DayOfWeek.MONDAY )    // Returns `LocalDate`, for the date of the first day (Monday) of that year-week.
.with (                       // Adjust to another `LocalDate` object, another date.
    TemporalAdjusters         // Utility class offering implementations of `TemporalAdjuster` interface.
    .dayOfWeekInMonth( 
        1 ,                   // nth day in the month, an ordinal number.
        DayOfWeek.SUNDAY      // The day-of-week for which we want the date of the nth.
    )                         // Returns an `TemporalAdjuster` object.
)                             // Returns a `LocalDate` object.

ISO 8601

The ISO 8601 standard defines a year-week as:

  • Starting on a Monday.
  • Week # 1 containing the first Thursday of the calendar year.

This means a week-based year:

  • Has either 52 or 53 complete weeks.
  • May include a few days from the previous and/or next calendar year.

ThreeTen-Extra

If your definition is the same, then I suggest adding the Three-Ten Extra library to your project.

YearWeek

Doing so gives you access to the YearWeek class.

YearWeek yw = YearWeek.of( y , w ) ;

Tip: Pass around your codebase objects of this class rather than mere int values enteredWeekNumber & enteredYear. Using objects brings type-safety, ensures valid values, and makes your code more self-documenting.

LocalDate

Get the date of the first day of that week.

LocalDate ld = yw.atDay( DayOfWeek.MONDAY ) ;

TemporalAdjuster

Use a TemporalAdjuster to get nth day-of-week of that month date’s month.

Fortunately, the utility class TemporalAdjusters gives us just such an adjuster.

TemporalAdjuster ta = TemporalAdjusters.dayOfWeekInMonth( 1 , DayOfWeek.SUNDAY ) ;

Apply the temporal adjuster to get another LocalDate object. The java.time classes use immutable objects. We get a fresh object rather than altering ("mutating") the original.

LocalDate firstSunday = ld.with( ta ) ;

If you want to get fancy, you could write your own implementation of a TemporalAdjuster to contain this functionality. I’ll leave that as an exercise for the reader.

CodePudding user response:

May be you could try something like below if your Week starts at the first day of the year

int enteredWeekNumber = 22;
int enteredYear = 2022;

LocalDate someSunday = LocalDate.now()
                                .withYear(enteredYear)
                                .with(ChronoField.ALIGNED_WEEK_OF_YEAR, enteredWeekNumber)
                                .with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));

or somthing like below, if you use ISO standard

LocalDate someSunday2 = LocalDate.now()
                                 .withYear(enteredYear)
                                 .with(WeekFields.ISO.weekOfYear(), enteredWeekNumber)
                                 .with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
  •  Tags:  
  • java
  • Related