I am trying to debug a problem in some legacy code.
I have narrowed the problem to the following method:
public String formatDateTimeFromCalendar (Calendar cal){
StringBuffer sb = new StringBuffer();
String hr = ""+cal.get(Calendar.HOUR_OF_DAY);
sb.append(String.format("%02d", hr));
sb.append(":");
sb.append(String.format("%02d", cal.get(Calendar.MINUTE)));
sb.append( " on ");
sb.append(String.format("%02d", cal.get(Calendar.DAY_OF_MONTH)));
sb.append( "/");
sb.append(String.format("%02d", cal.get(Calendar.MONTH)+1));
sb.append( "/");
sb.append( cal.get(Calendar.YEAR));
return sb.toString();
}
Debugging
Line 2 the cal
parameter is a future date. (2015-01-06T00:00:00.000Z)
After execution of line 3 with the first cal.get(
the cal
param's values have changed (to 2014-12-12T00:00:00.000Z)
Why/how could this be?
Here is where the calendar is being created:
Calendar startDateAndTime = Calendar.getInstance();
startDateAndTime.setTime(response.getStartDate().toGregorianCalendar().getTime());
startDateAndTime.set(Calendar.HOUR_OF_DAY, response.getStartTime().getHour());
startDateAndTime.set(Calendar.MINUTE, response.getStartTime().getMinute());
startDateAndTime.set(Calendar.SECOND, response.getStartTime().getSecond());
startDateAndTime.set(Calendar.MILLISECOND, response.getStartTime().getMillisecond());
response.getStartDate()
returns an XMLGregorianCalendar
Calendar class in Java is an abstract class that provides methods for converting date between a specific instant in time and a set of calendar fields such as MONTH, YEAR, HOUR, etc. It inherits Object class and implements the Comparable, Serializable, Cloneable interfaces.
Calendar. getInstance(). getTime() : Returns a Date object representing this Calendar's time value (millisecond offset from the Epoch(January 1, 1970 00:00:00.000 GMT (Gregorian).)
The getInstance() method in Calendar class is used to get a calendar using the current time zone and locale of the system. Syntax: public static Calendar getInstance() Parameters: The method does not take any parameters. Return Value: The method returns the calendar.
This is because calls of get
normalize the Calendar
in lenient mode, and validate it in strict mode:
returns the value of the given calendar field. In lenient mode, all calendar fields are normalized. In non-lenient mode, all calendar fields are validated and this method throws an exception if any calendar fields have out-of-range values. The normalization and validation are handled by the
complete()
method, which process is calendar system dependent.
It looks like your Calendar
object is in lenient mode, hence the normalization is performed. Normalization is dependent on the calendar instance.
This is source code of java.util.Calendar for get() method.
public int get(int field)
{
complete();
return internalGet(field);
}
complete() method checks if all fields were set in instance and could normalize date and time.
This is default implementation of complete() method
protected void complete()
{
if (!isTimeSet)
updateTime();
if (!areFieldsSet || !areAllFieldsSet) {
computeFields(); // fills in unset fields
areAllFieldsSet = areFieldsSet = true;
}
}
But you shouldn't think that your fields are necessary invalid. This could happen if you manually edited calendar instance calling set() method, it unconditionally sets isTimeSet and areFieldsSet to false enforcing recomputation on subsequent obtaining of data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With