Hi I have something weird happening. I am simply taking a calendar object, converting it to its individual parts, and putting it back into a calendar (with or without any change
As per my comments under your question , there is only difference in seconds and milliseconds between startCalendar
and calendarStart
time, because that values were not reset.
See DEMO
When you initialize the Calendar object, it is getting the current time including the current second and millisecond. The code provided sets the hour and minute, but it does not set the second and millisecond, leaving it as it was when the Calendar object was initialized. In order to set the second and nanosecond to zero, use:
StartCalendar.set(Year, Month, DayofMonth, Hour, Minute, 0,0);
In the documentation of Calendar.set, it is said :
Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR, MINUTE, and SECOND. Previous values of other fields are retained. If this is not desired, call clear() first.
The reason is that not all fields are set with this method, in you case, you don't have MILLISECOND
set. So it keep the value when the instance was created.
The call of Calendar.clear will
Sets all the calendar field values and the time value (millisecond offset from the Epoch) of this Calendar undefined.
A quick example :
Calendar c = GregorianCalendar.getInstance();
c.clear();
c.set(2019, Calendar.NOVEMBER, 03, 16, 15, 03);
System.out.println(c.getTime());
System.out.println(c.getTimeInMillis());
Sun Nov 03 16:15:03 CET 2019
1572794103000
Milliseconds being undefined will give 0
I suggest that you use java.time, the modern Java date and time API, for your date and time work. For example:
ZonedDateTime start = ZonedDateTime.now(ZoneId.systemDefault());
ZonedDateTime end = start;
System.out.println("Start: " + start);
System.out.println("End: " + end);
Output when I ran the code in my time zone just now:
Start: 2020-06-24T19:24:04.811+02:00[Europe/Copenhagen] End: 2020-06-24T19:24:04.811+02:00[Europe/Copenhagen]
A ZonedDateTime
is a date and time of day in some time zone. It’s the closest we come to a modern equivalent of GregorianCalendar
(the subclass of Calendar
that your code gave you). Which modern class to use varies with more precise requirements, so sometimes you will prefer to use for example LocalDate
, OffsetDateTime
or even LocalTime
.
To truncate the values to whole minutes (setting seconds and fraction of second to 0):
ZonedDateTime start = ZonedDateTime.now(ZoneId.systemDefault())
.truncatedTo(ChronoUnit.MINUTES);
Start: 2020-06-24T19:24+02:00[Europe/Copenhagen]
ZonedDateTime
and the other classes of java.time offer plenty of ways to modify the values obtained. For example:
ZonedDateTime end = start.plusDays(2).withHour(13);
End: 2020-06-26T13:24+02:00[Europe/Copenhagen]
If you want to create the end time manually using only selected fields from the start time:
ZonedDateTime end = ZonedDateTime.of(
2021, start.getMonthValue(), start.getDayOfMonth(),
start.getHour(), 30, 0, 0, start.getZone());
End: 2021-06-24T19:30+02:00[Europe/Copenhagen]
Part of the answer is already in the other answers: The set
methods of Calendar
set only the fields they promise to set and leave other fields unchanged where possible. While this is probably expected from the set(int field, int value)
method, it often surprises with the set(int year, int month, int date)
method and even more with set(int year, int month, int date, int hourOfDay, int minute)
and set(int year, int month, int date, int hourOfDay, int minute, int second)
. In general while well intended the Calendar
class and its subclasses are poorly and confusingly designed and cumbersome to work with. This is the main reason why I recommend java.time above.
The other part of the answer is that Calendar
calculates its fields leniently. So when you look at the Calendar
object in your debugger after calling set
, it will contain a lot of garbage values. Calling getTime()
forces the Calendar
to compute its fields, so after that call the way it looks in the debugger should make more sense. Again it’s confusing behaviour, and it can also sometimes be observed without using the debugger.
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
org.threeten.bp
with subpackages.java.time
was first described.java.time
to Java 6 and 7 (ThreeTen for JSR-310).