-2

I am setting a Calendar day of month with an int value but when I check the value again the day of month from the created calendar it is 1 more than I set it to. And I am not sure why?

Here is an example:

System.out.println("DEBUG: Reminder day of month = " + reminder.getReminderDayofMonth());

calendar.set(Calendar.YEAR, reminder.getReminderYear());                   
calendar.set(Calendar.MONTH, reminder.getReminderMonth());
calendar.set(Calendar.DAY_OF_MONTH, reminder.getReminderDayofMonth());
calendar.set(Calendar.HOUR, reminder.getReminderHour());
calendar.set(Calendar.MINUTE, reminder.getReminderMinute());

System.out.println("DEBUG: Calendar day of month = " + calendar.get(Calendar.DAY_OF_MONTH));

I did the println so you can see the value in and the value out. I would expect that calling calander.get(Calander.DAY_OF_MONTH) would return the same value as I put into it. But it doesn't, I get:

DEBUG: Reminder day of month = 18
DEBUG: Calendar day of month = 19

I am sure it is probably something simple but I have no idea why they would be different and I can't find anything in the docs to explain the discrepancy

What is the problem?

Thanks for your help

Nicholas Muir
  • 2,897
  • 8
  • 39
  • 89
  • Why the mark down with no explanation? – Nicholas Muir Dec 17 '17 at 16:14
  • Have you also verified/ensured that `reminder.getReminderMonth()` is zero-based? – Meno Hochschild Dec 17 '17 at 16:23
  • Thanks for your response. I don't see how that is relevant when you can see that reminder.getReminderDayOfMonth() has an int value of 18. This is why I did the system out before hand to ensure an int of 18 was going in. whats coming out is 19. – Nicholas Muir Dec 17 '17 at 16:26
  • @MenoHochschild is it a problem with the Calendar being 0 based. The docs do not specify? – Nicholas Muir Dec 17 '17 at 16:32
  • Actually can you explain why month would effect Day of Month? I know Month is zero based in calendar. – Nicholas Muir Dec 17 '17 at 16:36
  • What happens if you print the day of month before setting the hour and minute? – Ole V.V. Dec 17 '17 at 17:17
  • As an aside you probably meant `HOUR_OF_DAY`, not `HOUR`. – Ole V.V. Dec 17 '17 at 17:17
  • Hi Ole thanks. Yeah is you check my code I did print day of month before hand. And hour is just from my custom object. It turned out to be a weird issue with the calendar being created outside the if statement. When I moved it inside it fixed the error. Not sure what was causing it but at least it is fixed now. – Nicholas Muir Dec 17 '17 at 17:27
  • 1
    Could it be that `getReminderHour()` returns 24 or greater? I think this would explain the observation. – Ole V.V. Dec 17 '17 at 18:05
  • When the `Calendar` class gets troublesome (it would be far from the first time), the standard solution is to move to `ZonedDateTime` or a similar class from `java.time`, the modern Java date and time API also known as JSR-310. To use it on not-brand-new Android devices, you need [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP), the Android Backport (from Java 8) of JSR-310. – Ole V.V. Dec 17 '17 at 18:09
  • 3
    My remark about the zero-based months was just a shot in the dark. The main problem of your question is however that you have not yet posted your real input data for your `reminder`-object so other have no chance to reproduce or verify your observations. – Meno Hochschild Dec 18 '17 at 09:14

1 Answers1

1

TL:DR

LocalDateTime ldt = LocalDateTime.of(
    reminder.getReminderYear(),
    reminder.getReminderMonth() + 1,  // Add one to adjust from zero-based counting.
    reminder.getReminderDayofMonth(),
    reminder.getReminderHour(),
    reminder.getReminderMinute()
);

java.time

I suggest you put an end to using the very old and long outmoded Calendar class. Today we have so much better in java.time, the modern Java date and time API also known as JSR-310. The above code gives you the equivalent of what I think you were trying. I assumed getReminderMonth() returned 0-based month, so added 1 since the modern API numbers months from 1 just as humans do. If you can, I recommend you use an OffsetDateTime or ZonedDateTime to make the point on the time line unambiguous.

Question: Can I use the modern API with my Java version?

If using at least Java 6, you can.

  • In Java 8 and later the new API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR-310; link below).
  • On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. See the linked question below.

What went wrong in your code

I think the observed date increment happens when both of the following conditions are met:

  • Your code is running in the afternoon, that is at 12 noon or later in the Calendar’s time zone (typically the JVM’s time zone, in turn typically your local time zone).
  • getReminderHour() returns an hour in the afternoon, that is, 12 or later.

I cannot be 100 % sure since you haven’t shown us the code that produced your bug. But very likely your Calendar instance was created with the current time (Calendar.getInstance() and new GregorianCalendar(), for example, do this). In the afternoon it is obviously created with a time in PM. Then when you call calendar.set(Calendar.HOUR, reminder.getReminderHour()), this tries to set the hour within PM, but since the hour is 12 or greater, this overflows into AM of the following day. An hour of 14 (PM), for example, becomes 2 AM the next day.

If I am correct, the problem may seem solved not because you moved the creation of the calendar object inside your if statement, but because either you ran your program in the morning or the reminder hour was in the morning (before 12 noon). And your bug may surface again next time both the above-mentioned conditions apply,

Links

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thank you for this. I hadn't looked at the code since asking this question. I overwrote the code with hour under 12 and the problem goes away. So that was it. Appreciate the help. – Nicholas Muir Dec 29 '17 at 07:55