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));