Java Date giving different dates

I need my Java Android app to extract and compare dates, but it's all a mess to get the correct date.

    TimeZone timeZone = TimeZone.getTimeZone("GMT");
    Calendar calendar = Calendar.getInstance(timeZone);

    Date currentTime = calendar.getTime();
    Log.i(logtag, "Date currentTime="+currentTime);

    String tidspunkt = calendar.get(Calendar.YEAR)+ "." + calendar.get(Calendar.MONTH)+"."+calendar.get(Calendar.DAY_OF_MONTH)+" "+calendar.get(Calendar.HOUR_OF_DAY)+":"+calendar.get(Calendar.MINUTE)+":"+calendar.get(Calendar.SECOND);
    Log.i(logtag, "calendar.get(Calendar.YEAR)="+tidspunkt);

    String tidspunkt2 = currentTime.getYear()+ "." + currentTime.getMonth()+"."+currentTime.getDay()+" "+currentTime.getHours()+":"+currentTime.getMinutes()+":"+currentTime.getSeconds();
    Log.i(logtag, "currentTime.getYear()="+tidspunkt2);

    currentTime.setYear(calendar.get(Calendar.YEAR));
    currentTime.setMonth((calendar.get(Calendar.MONTH)));
    currentTime.setDate(calendar.get(Calendar.DAY_OF_MONTH));
    currentTime.setHours(calendar.get(Calendar.HOUR_OF_DAY));
    currentTime.setMinutes(calendar.get(Calendar.MINUTE));
    currentTime.setSeconds(calendar.get(Calendar.SECOND));
    Log.i(logtag, "Date currentTime edited="+currentTime);

    String tidspunkt3 = currentTime.getYear()+ "." + currentTime.getMonth()+"."+currentTime.getDay()+" "+currentTime.getHours()+":"+currentTime.getMinutes()+":"+currentTime.getSeconds();
    Log.i(logtag, "currentTime.getYear() edited="+tidspunkt3);

Actual time when running: Mon 10th of January 2022, 22:29

Results:

  • Date currentTime=Mon Jan 10 22:29:53 GMT+01:00 2022 (correct date)
  • calendar.get(Calendar.YEAR)=2022.0.10 21:29:53 (wrong month, wrong hour)
  • currentTime.getYear()=122.0.1 22:29:53 (wrong year, wrong month, wrong day)
  • Date currentTime edited=Tue Jan 10 21:29:53 GMT+01:00 3922 (wrong year, wrong weekday, wrong hour)
  • currentTime.getYear() edited=2022.0.2 21:29:53 (wrong month, wrong day, wrong hour)

I need to save old dates as objects, and then be able to pull the correct year, month number, day number etc from those objects. So I need an object which I can both extract dates from, and set to any old date I need.


Solution 1:

This is why java.util.Date and java.util.Calendar are terrible APIs that you should replace with java.time. Have you read the doc on Date.setYear? Or seen that Calendar.JANUARY is 0?

You can use java.time with Android with desugaring.

Solution 2:

Avoid legacy classes

Never use TimeZone, Calendar, Date. Do not waste your time trying to understand their bizarre behavior. Sun, Oracle, and the JCP community gave up on those classes years ago, and do should you. These terrible classes were years ago supplanted by the modern java.time classes defined in JSR 310.

java.time

Capture the current moment as seen in UTC (an offset of zero).

Instant instant = Instant.now() ;

The Instant class is a basic building block class with limited features. For more flexibility, convert to either OffsetDateTime or ZonedDateTime.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
ZonedDateTime zdt = instant.atZone( ZoneId.of( "Asia/Tokyo" ) ) ;

Note that all three of these objects here, instant, odt, & zdt, all represent the very same simultaneous moment, the same single point on the time line.

To generate text representing a moment, you are working much too hard. Let DateTimeFormatter do the heavy lifting.

Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG ).withLocale( locale ) ;
String output = zdt.format( f ) ;

An implementation of java.time is built into Android 26+. For earlier Android, the latest tooling provides most of the java.time functionality via “API desugaring”. If that does not work for you, use a back-port of java.time, the ThreeTenABP project.