Reputation: 19
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
Reputation: 86389
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.
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
org.threeten.bp
with subpackages.java.time
was first described.java.time
to Java 6 and 7 (ThreeTen for JSR-310).Upvotes: 0
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