JDK-8229471 : Calendar under a specific timezone changes HOUR field when MILLISECOND field is changed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:i18n
  • Affected Version: 11,13,14
  • Priority: P4
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2019-08-12
  • Updated: 2019-09-13
  • Resolved: 2019-09-13
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Windows 10, Java 64
the issue is reproducible on Java 7_u25 and java 8_221

A DESCRIPTION OF THE PROBLEM :
If you have a Calendar set to a specific timezone (e.g. "Europe/Budapest"), and you change its MILLISECOND field, the hour field will be incorrectly changed as well.

Work-around: performing a get on the HOUR field, before modifying the MILLISECOND filed will prevent the bug.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
TimeZone tz = TimeZone.getTimeZone("Europe/Budapest");
Calendar calendar = Calendar.getInstance();
// Work-around: uncomment this line to prevent the java Calendar bug		
// System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
calendar.set(Calendar.MILLISECOND, 0);
System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Setting the MILLISECOND field won't change the HOUR field
ACTUAL -
Setting the MILLISECOND field changes the HOUR field

---------- BEGIN SOURCE ----------
import java.util.Calendar;
import java.util.TimeZone;

public class TestCalendar {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		TimeZone tz = TimeZone.getTimeZone("Europe/Budapest");
		Calendar calendar = Calendar.getInstance();
		// Work-around: uncomment this line to prevent the java Calendar bug		
		// System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
		calendar.set(Calendar.MILLISECOND, 0);
		System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
		System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
		System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
		System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
See source code commented out line

FREQUENCY : always



Comments
According to JDK-4177484, calendar fields will not be updated on setTimeZone() call until a get() method occurs. So if some set() method is issued during that period, the time in the calendar object is re-calculated based on the new time zone (Budapest) on the later get() call. Thus, in that case, hour is adjusted to that zone's time.
13-09-2019

When calendar is created using the constructor passing the timezone, Calendar.getInstance(tz) , the issue is not reproducible as seen in above comment. Attached test case has been provided by submitter to reproduce the issue. JDK 11.0.4 - Fail JDK 13-ea - FAil JDK 14-ea - Fail Output: BEFORE: Calendar time is: 22/08/2019 12:20:38 307 IST HOUR: 0 MINUTE: 20 SECOND: 38 MILLISECOND: 0 AFTER: Calendar time is: 22/08/2019 03:50:38 000 IST
22-08-2019

To submitter: Using the test case provided in the bug report, I am not able to reproduce the issue that you have described. Here is the output of the test case, as you can see the hour field of the time has not changed, only the ms field has changed from 179 to 0 : Current time : 2019-08-13T11:47:49.179+02:00[Europe/Budapest] HOUR: 11 MINUTE: 47 SECOND: 49 MILLISECOND: 0 Please let me know if you have any inputs that may help reproduce the issue that you have described.
13-08-2019