This is August 2025:
August 2025
Mon Tue Wed Thu Fri Sat Sun
1 2 3
4 5 6 7 8 9 10
--> 11 12 13 14 15 (16) 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Given a date (e.g. 2025-08-16) I want to get the beginning of the week. The first day of the week is Monday, so the beginning of the week is 2025-08-11.
I used this code:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
public class Sample {
public static void main(String[] args) {
Calendar dt = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome"));
dt.setFirstDayOfWeek(Calendar.MONDAY);
// set to 2025-08-16
dt.set(Calendar.YEAR, 2025);
dt.set(Calendar.MONTH, Calendar.AUGUST);
dt.set(Calendar.DATE, 16);
//dt.getTimeInMillis(); // <-- UNCOMMENT THIS AFTER FIRST RUN
dt.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
// SHOULD BE 2025-08-11
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(dt.getTime()));
}
}
Running it, it returns 2025-08-04, which is completely wrong. But uncommenting the line marked with "UNCOMMENT THIS", which is a get operation, the actual result becomes the expected one (2025-08-11).
Is it a JDK bug? How can I explain it?
Use only java.time classes for date-time work. Never use Calendar
.
LocalDate
.of( 2025 , Month.AUGUST , 16 )
.with(
TemporalAdjusters.previousOrSame ( DayOfWeek.MONDAY )
)
Never use the terribly flawed legacy date time classes such as Date
, Calendar
, and SimpleDateFormat
.
Use only the modern java.time classes.
Represent a date with java.time.LocalDate
.
LocalDate ld = LocalDate.of( 2025 , Month.AUGUST , 16 ) ;
Use a TemporalAdjuster
(class name is singular) to get the previous Monday, or get the same date if it is a Monday. The utility class TemporalAdjusters
(class name is plural) provides the adjuster you need.
TemporalAdjuster adjuster = TemporalAdjusters.previousOrSame ( DayOfWeek.MONDAY ) ;
Apply the adjuster to produce a LocalDate
object.
LocalDate previousOrSameMonday = ld.with( adjuster ) ;