Jodatime vs ThreeTenABP (Android Date/Time tool comparison)

Reaching the infamous dex method limit kinda sucks. Which is why I started to trim libraries in my app instead of just going the Multidex route. With the help of this nifty APK method count tool , I’ve been able to identify some libraries I might reconsider using.

Jodatime has 4713 methods and ThreeTenABP has 2827 methods (debug apk)

I’ve been using the Jodatime port  for a while now. It makes dealing with date and time functionality easy. I came across ThreeTenABP which is an Android backport of  Java 8’s JSR310 implementation. The functionality between the 2 seems comparable for what I use Jodatime for in my app. What stood out for me though was the method count.

Comparing Jodatime  (2.9.2) and ThreeTenABP (1.0.3) , the latter has a significantly lower method count. Jodatime has 4713 methods and ThreeTenABP has 2827 methods (debug apk). That difference was big enough for me to consider replacing my implementation and it was not as painful as I anticipated. I went through Jodatime’s quick start guide and tried implementing the same examples using ThreeTenABP.

Jodatime:


DateTime dt = DateTime.now();
int jd = dt.getDayOfMonth();
int jm = dt.getMonthOfYear();
int jy = dt.getYear();
Log.d(TAG,"Joda : "+ dt.toString());
Log.d(TAG,"Joda : [day: "+jd+"] [month: "+jm+"] [year: "+jy+"]");
Log.d(TAG,"Joda : [day: "+dt.dayOfWeek().getAsText()+"] [month: "+dt.monthOfYear().getAsText()+"] [year: "+dt.year().getAsText()+"]");
dt.withYear(2000);
dt.plusHours(2);
Log.d(TAG,"Joda : "+dt.toString());
String frenchShortName = dt.monthOfYear().getAsShortText(Locale.FRENCH);
boolean isLeapYear = dt.year().isLeap();
DateTime rounded = dt.dayOfMonth().roundFloorCopy();
Log.d(TAG,"Joda : [french Short: "+frenchShortName+"] [leapyear: "+isLeapYear+"] [rounded: "+rounded+"]");
dt = new DateTime(2005, 3, 26, 12, 0, 0, 0);
Log.d(TAG,"Joda : "+ dt.toString());
DateTime plusPeriod = dt.plus(Period.days(1));
Log.d(TAG,"Joda : +1day "+ plusPeriod.toString());
DateTime plusDuration = dt.plus(new Duration(24L*60L*60L*1000L));
Log.d(TAG,"Joda : +24h "+ plusDuration.toString());
DateTime today = DateTime.now();
DateTime yesterday = today.minusDays(1);
Hours diff = Hours.hoursBetween(today,yesterday);
Log.d(TAG,"Joda : hours between "+ diff.getHours());

ThreeTenABP:


LocalDateTime ldt = LocalDateTime.now();
int ld = ldt.getDayOfMonth();
int lm = ldt.getMonthValue();
int ly = ldt.getYear();
Log.d(TAG,"3ten : "+ldt.toString());
Log.d(TAG,"3ten : [day: "+ld+"] [month: "+lm+"] [year: "+ly+"]");
Log.d(TAG,"3ten : [day: "+ldt.getDayOfWeek().name()+"] [month: "+ldt.getMonth().name()+"] [year: "+ldt.getYear()+"]");
ldt.withYear(2000);
ldt.plusHours(2);
Log.d(TAG,"3ten : " +ldt.toString());
String frenchShortName = ldt.getMonth().getDisplayName(TextStyle.SHORT,Locale.FRENCH);
boolean isLeapYear = false; // could not find a matching function
LocalDateTime rounded = ldt.truncatedTo(ChronoUnit.DAYS);
Log.d(TAG,"3ten : [french Short: "+frenchShortName+"] [leapyear: "+isLeapYear+"] [rounded: "+rounded+"]");
ldt = LocalDateTime.of(2005, 3, 26, 12, 0, 0, 0);
Log.d(TAG,"3ten : "+ ldt.toString());
LocalDateTime plusPeriod = ldt.plusDays(1);
Log.d(TAG,"3ten : +1day: "+ plusPeriod.toString());
LocalDateTime plusDuration = ldt.plus(24,ChronoUnit.HOURS);
Log.d(TAG,"3ten : +24h : "+ plusDuration.toString());
LocalDateTime today = LocalDateTime.now();
LocalDateTime yesterday = today.minusDays(1);
org.threeten.bp.Duration diff = org.threeten.bp.Duration.between(today,yesterday);
Log.d(TAG,"3ten : hours between "+ diff.toHours());

You can get most of the functionality provided by Jodatime from ThreeTenABP. I also noticed that Jodatime now seems to have the JSR-310 implementations as well. The only reason I ended up changing was because of the method count. Your use case might vary to mine.