Java Calendar instance increments DAY_OF_MONTH as a side effect of decrementing (only) HOUR or MINUTE

Viewed 522

I have an unfinished Android app with a main activity with a TimePicker (@+id/tyme), a DatePicker (@+id/date), and a TextView (@+id/dropTime) for displaying a "DateTime"-like datum that for some reason I need two views to specify.

Because the Javadocs deprecate all attempts to extract DateTime-field-type values from a Date instance, I thought to use the Calendar class to represent the user-selected combination of year,month,day,hour,minute,second. I find that I often (but not always) can't decrement the hour or minute fields without simultaneously incrementing the day-of-month field. Here's my event handler for the DatePicker:

        date = (DatePicker) findViewById(R.id.date);
        // h/t O'one https://stackoverflow.com/a/34952495/948073
        date.init(
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH),
                new DatePicker.OnDateChangedListener() {
                    @Override
                    public void onDateChanged(DatePicker datePicker, int y, int m, int d) {
                        System.out.println("onDateChanged(tp,"+y+","+m+","+d+")");
                        calendar.set(Calendar.YEAR, y);
                        calendar.set(Calendar.MONTH, m);
                        calendar.set(Calendar.DAY_OF_MONTH, d);
                        updateDropTime();
                    }
                }
        );

And the TimePicker. Note the explicit backup-and-restore of the y/m/d fields in a vain attempt to stamp out suspected cross-contamination of y:m:d during h:m:s changes:

        private TimePicker time;
        dropTime = (TextView) findViewById(R.id.dropTime);
        updateDropTime();
        time = (TimePicker) findViewById(R.id.tyme);


        time.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
            public void onTimeChanged(TimePicker tp, int h, int m) {
                System.out.println("onTimeChanged(tp,"+h+","+m+")");
                // Save state of y/m/d portion of calendar
                int y = calendar.get(Calendar.YEAR);
                int mo = calendar.get(Calendar.MONTH);
                int d = calendar.get(Calendar.DAY_OF_MONTH);
                // Set h and m fields of calendar based on user input
                calendar.set(Calendar.HOUR, h);
                calendar.set(Calendar.MINUTE, m);
                // Restore state of y/m/d fields
                calendar.set(Calendar.YEAR, y);
                calendar.set(Calendar.MONTH, mo);
                calendar.set(Calendar.DAY_OF_MONTH, d);
                // In theory y/m/d portion of datetime should be unchanged
                updateDropTime();
            }
        });

Both these event handlers call updateDropTime(), which looks like this:

private void updateDropTime() {
    String disp = DateFormat.getDateTimeInstance().format(calendar.getTimeInMillis());
    dropTime.setText(disp);
}

I suspect that something in the method chain leading to a value for disp is where the seemingly chaotic behavior takes place, seeing as I would think I've systematically stamped out any changes to date fields that could conceivably be side effects of changes to time fields.

1 Answers
Related