0

I have a small application which simply sets the time and date of a Calendar and then retrieves it.

Currently when using my application on devices up to API24 its retrieves the correct date which was originally set. But if you run the application on a device higher than API 24 then the date returned is one day later than the desired result.

My code as below

Setting the date of the calendar....

myCalendar.set(Calendar.YEAR, 2018 );
myCalendar.set(Calendar.DAY_OF_MONTH, 3);
myCalendar.set(Calendar.MONTH, 0);
myCalendar.set(Calendar.HOUR, 18);
myCalendar.set(Calendar.MINUTE, 30);

Retrieving the date

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String dates = sdf.format(myCalendar.getTime());


StringTokenizer revDate = new StringTokenizer(dates, "/");
String txtDays = revDate.nextToken();
String txtMonths = revDate.nextToken();
String txtYears = revDate.nextToken();

String reversedDate = txtDays + txtMonths + txtYears;

On phones below API 24 we receive the correct date 03/01/2018 on API 24 above I receive 04/01/2018

I've tested my application on multiple virtual devices and real phones, all using the same time zone its only when using API 24 above that this strange issue occurs.

Thanks

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Steven
  • 49
  • 9
  • Possible duplicate of [Discrepancy in Java Calendar set Day Of Month vs Get Day Of Month](https://stackoverflow.com/questions/47856962/discrepancy-in-java-calendar-set-day-of-month-vs-get-day-of-month) – Ole V.V. Jan 02 '18 at 07:22
  • As an aside, on Android consider throwing away the long outmoded `Calendar` and the notoriously troublesome `SimpleDateFormat`, and adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Jan 02 '18 at 07:27
  • You want `03012018`? Also aside, is there a point in `revDate` that I haven’t seen? The way you use it, it doesn’t seem to reverse anything. – Ole V.V. Jan 02 '18 at 07:32

3 Answers3

2

I should like to contribute the modern version of your code. Barns’ answer is correct and should make sure your code behaves as it should. But I prefer:

    LocalDateTime myDateTime = LocalDateTime.of(2018, Month.JANUARY, 3, 18, 30);
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("ddMMuuuu");
    String reversedDate = myDateTime.format(dtf);

This produces a reversedDate of 03012018 to denote 3 January 2018. If you needed the order of day-of-month, month and year reversed somehow, just modify the order in the format pattern string, for example uuuuMMdd or MMdduuuu.

I recommend the modern classes. Even though on not-too-brand-new Android devices, Calendar and SimpleDateFormat are what you get built-in, those classes are long outmoded and the latter in particular notoriously troublesome. So in my snippet I am assuming you have added ThreeTenABP to you Android project to allow you to use JSR 310, also known as java.time, the modern Java date and time API. This is so much nicer to work with. Import org.threeten.bp.LocalDateTime, org.threeten.bp.Month and org.threeten.bp.format.DateTimeFormatter. Also StringTokenizer is a legacy class. Its documentation says “It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.”

What went wrong in your code?

You haven’t given us a complete and reproducible example, so I cannot be sure, but strongly I suspect that you see the incorrect date when your code is running in the afternoon, that is at 12 noon or later in the myCalendar’s time zone (typically the JVM’s time zone, in turn typically your local time zone). Very likely myCalendar 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 myCalendar.set(Calendar.HOUR, 18), this tries to set the hour within PM, but since the hour is 18, this overflows into AM of the following day, becoming 6 AM the next day.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thank you Ole for your detailed solution and some very key points which I will take into consideration whilst working on my project. Also brilliant links which I will keep bookmarked for future use. I have also up voted your answer as this would be useful for other users. – Steven Jan 02 '18 at 13:15
  • @OleV.V. I agree that the solution I provided was not the most elegant, but it was purely based on the OP's Question. I did not know what the rest of the OP's code looked like or what the requirements are for his project. In general I would not suggest creating `Date` value in the manner the OP did--it is fragile. I like your in-depth explanation! – Barns Jan 02 '18 at 15:33
1

You should use "HOUR_OF_DAY" instead of "HOUR" when you set the time and you are using 24-hr system.

Try this:

myCalendar.set(Calendar.YEAR, 2018 );
myCalendar.set(Calendar.DAY_OF_MONTH, 3);
myCalendar.set(Calendar.MONTH, 0);
myCalendar.set(Calendar.HOUR_OF_DAY, 18);
myCalendar.set(Calendar.MINUTE, 30);

According to JAVA Docs:

HOUR_OF_DAY

public static final int HOUR_OF_DAY Field number for get and set indicating the hour of the day. HOUR_OF_DAY is used for the 24-hour clock. E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22.

HOUR

public static final int HOUR Field number for get and set indicating the hour of the morning or afternoon. HOUR is used for the 12-hour clock (0 - 11). Noon and midnight are represented by 0, not by 12. E.g., at 10:04:15.250 PM the HOUR is 10.

Community
  • 1
  • 1
Barns
  • 4,850
  • 3
  • 17
  • 31
0

I think you should use getInstance() method of calendar class because Calendar.getInstance() method gets a calendar using the specified time zone and specified locale.

for eg:

    DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
    Date dat = Calendar.getInstance().getTime();
    String s3 = df.format(dat);

this works perfectly fine with my program and gives me desired result along with manipulation of date in the desired format.

bina
  • 1
  • 1
  • This Answer does not address the OP's question. "MM/dd/yyyy HH:mm:ss" is neither the input format the OP uses nor the output format the OP requires. This solution does not construct the `Date` the OP needs. This solution simply takes the `DateTime` at that particular moment and formats it. There is no merit to this Answer. – Barns Jan 02 '18 at 17:03