csgbsk
csgbsk

Reputation: 19

Crutch with the Calendar in Java

I'm writing an app for android. On the start of it I create a Calendar, filling such containers as YEAR, MONTH, DAY_OF_MONTH, ERA and time zone as GMT.

I get something like this java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=java.util.SimpleTimeZone[id=GMT,offset=0,dstSavings=3600000,useDaylight=false,startYear=0,startMode=0,startMonth=0,startDay=0,startDayOfWeek=0,startTime=0,startTimeMode=0,endMode=0,endMonth=0,endDay=0,endDayOfWeek=0,endTime=0,endTimeMode=0],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2021,MONTH=3,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=14,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]

Later on I need to get a string like "14-04-2021", so I create a Date variable using getTimeInMillies for the Calendar before. All the fields of it become filled with zeros.

After parsing a JSON, I need to create a map with Calendar keys. It looks like this.

String key = keys.next();                                                                                                              
Date d = dateFormat.parse(key);                                                                                                        
String rate = String.valueOf(rates.getJsonObject(key).get(get_curr_inf(get_curr_to_r())));                                             
Double rate_ = Double.parseDouble(rate);                                                                                               
Calendar cal = new GregorianCalendar();                                                                                                
cal.setTime(d);                                                                                                                        
Calendar tmp = new GregorianCalendar(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));                 
tmp.setTimeZone(TimeZone.getTimeZone("GMT"));                                                                                          
tmp.set(Calendar.ERA, 1);                                                                                                              
long f = tmp.getTimeInMillis();                                                                                                        
data.put(tmp, rate_);                                                                                                                  

I do it in such a strange way as it needs to be exactly similar to the previous Calendar, cause i parse map using it.

Is there any way to make it look better?

Upvotes: 0

Views: 230

Answers (2)

Anonymous
Anonymous

Reputation: 86389

java.time

The first answer is to change your map to use LocalDate as key instead of Calendar. Two LocalDate objects denoting the same day will always be equal and produce the same hash code, so are ideal as map keys. Follow the answer by Basil Bourque.

The second answer, if for some reason you cannot change the type of the map keys, you can still produce an old-fashioned Calendar object more nicely using java.time, the modern Java date and time API.

    String key = "14-04-2021";
    LocalDate date = LocalDate.parse(key, DATE_FORMATTER);
    ZonedDateTime zdt = date.atStartOfDay(ZoneOffset.UTC);
    GregorianCalendar tmpCal = GregorianCalendar.from(zdt);
    System.out.println(tmpCal);

I used this formatter:

private static final DateTimeFormatter DATE_FORMATTER
        = DateTimeFormatter.ofPattern("dd-MM-uuuu");

And output is:

java.util.GregorianCalendar[time=1618358400000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2021,MONTH=3,WEEK_OF_YEAR=15,WEEK_OF_MONTH=3,DAY_OF_MONTH=14,DAY_OF_YEAR=104,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]

It is not completely equal to the result you had, so will not be compatible with Calendar objects produced your old way. One difference is that all fields are set. java.time cannot produce a Calendar with only selected fields set as you had before. The other difference could be eliminated: my time zone is UTC instead of GMT. In practice they are the same. To get GMT, use ZoneId.of("GMT") instead of ZoneOffset.UTC.

So if you can enforce that now all map keys are produced in the new way, I should say that you are set.

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Upvotes: 0

Basil Bourque
Basil Bourque

Reputation: 340230

Never use Calendar. That terrible class was supplanted years ago by the modern java.time classes.

For a date-only value without time-of-day and without time zone, use LocalDate.

On the start of it I create a Calendar, filling such containers as YEAR, MONTH, DAY_OF_MONTH, ERA and time zone as GMT.

LocalDate ld = LocalDate.of( 2021, Month.APRIL , 14 ) ;

I need to get a string like "14-04-2021"

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu" ) ;
String output = ld.format( f ) ;

I need to create a map with Calendar keys

Map< LocalDate , … > map = new … ;
map.put( ld , … ) ;

The java.time classes are built into Android 26 and later. The latest Android tooling brings much of that functionality to earlier Android by way of API desugaring.

Upvotes: 2

Related Questions