<i18n dev> Calendar.set(Calendar.DAY_OF_WEEK, ...) changes times as well
Lothar Kimmeringer
job at kimmeringer.de
Tue Mar 12 14:20:42 UTC 2024
Hello,
this might be Dunning Kruger at play (at least my Imposter Syndrom
tells me it is ;-) but I think I've found a bug in Calendar, when
working with a different timezonethan the default one.
Attached you can find my test case that is showing the effect but
it breaks down to the following:
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1709269200000L); // March 01 2024 06:00:00 CET
cal.setTimeZone(TimeZone.getTimeZone(TIMEZONE));
assertEquals("Fri Mar 01 06:00:00 CET 2024", cal.getTime().toString(), "check date before change");
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
assertEquals("Mon Feb 26 06:00:00 CET 2024", cal.getTime().toString(), "check date after change");
If TIMEZONE is the system's default, the test goes through, if it differs,
the offset time is added to the resulting date after setting the day of
the week. With Europe/Berlin (+0100 at that date) as default and
America/New_York (-0500 at that date) as the timezone being set to the
Calendar, the result is Mon Feb 26 12:00:00 CET 2024 (previous time plus
+1 minus -5).
The workaround for this is using Calendar.add instead of set:
cal.add(Calendar.DAY_OF_YEAR, -(cal.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY));
sets the day to monday without changes to the time.
Tested with
- Java 8.0.312_win_x64
- Java 11.0.20.1_win_x64
- Java 17.0.7_win_x64
- Java 21.0.0_win_x64
Thanks and best regards,
Lothar Kimmeringer
-------------- next part --------------
import static org.junit.jupiter.api.Assertions.*;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class __Test_CalendarSetWeekday {
private Locale defaultLocale;
private TimeZone defaultTimeZone;
@BeforeEach
public void setup() {
defaultLocale = Locale.getDefault();
defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
}
@AfterEach
public void tearDown() {
Locale.setDefault(defaultLocale);
TimeZone.setDefault(defaultTimeZone);
}
@Test
void testCalAddingBerlinVsNewYork() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1709269200000L); // March 01 2024
cal.setTimeZone(TimeZone.getTimeZone("America/New_York"));
assertEquals("Fri Mar 01 06:00:00 CET 2024", cal.getTime().toString(), "check date before change");
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
assertEquals("Mon Feb 26 06:00:00 CET 2024", cal.getTime().toString(), "check date after change");
}
@Test
void testCalAddingBerlinVsBerlin() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1709269200000L); // March 01 2024 06:00:00 CET
cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
assertEquals("Fri Mar 01 06:00:00 CET 2024", cal.getTime().toString(), "check date before change");
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
assertEquals("Mon Feb 26 06:00:00 CET 2024", cal.getTime().toString(), "check date after change");
}
}
More information about the i18n-dev
mailing list