javaerrorprone

Get Day, Month, Year from Java Calendar instance


I have an Instant derived from a Java Calendar, e.g. c.toInstant(), and now in a different location convert that to a custom Date object that needs a day of the month, month, and year. I tried:

    if (instance.isSupported(ChronoField.DAY_OF_MONTH) && instance.isSupported(ChronoField.MONTH_OF_YEAR) && instance.isSupported(ChronoField.YEAR)) {
      return new com.company.common.Date()
          .setDay(instance.get(ChronoField.DAY_OF_MONTH))
          .setMonth(instance.get(ChronoField.MONTH_OF_YEAR))
          .setYear(instance.get(ChronoField.YEAR));
    }

But when I try to compile ErrorProne throws:

...impl/utils/DateUtils.java:21: error: [TemporalAccessorGetChronoField] TemporalAccessor.get() only works for certain values of ChronoField.
          .setDay(instance.get(ChronoField.DAY_OF_MONTH))
                              ^

I'm not sure why I can't find an answer for this anywhere, but after some searching I came up with nothing helpful -- though I probably missed something.


Solution

  • Instant is only a timestamp - it only provides seconds, millis and nanos.

    If you start with a Calendar instance in the first place you should be able to simply use

    calendar.get(Calendar.YEAR)
    calendar.get(Calendar.MONTH) + 1
    calendar.get(Calendar.DAY_OF_MONTH)
    

    directly to fetch the date values and skip the conversion to Instant.

    Note that in Calendar month is a zero-based value. You usually have to add one to get to value one would commonly expect.

    If you prefer working with the newer time API you can fetch dates and time from a ZonedDateTime like

        Calendar calendar = Calendar.getInstance();
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId());
    
        zonedDateTime.getYear();
        zonedDateTime.getMonthValue();
        zonedDateTime.getDayOfMonth();
    

    I don't see a direct advantage for the example given, beyond getting the "correct" value for month here directly. It could be useful if you want to do any additional work with the date value beyond just reading its contents.

    Generally speaking ZonedDateTime and all other types from the java.time package provide the more robust API and functionality compared to the older Calendar type. Therefore avoid the calendar type for any new code