Is Core Library Desugaring the holy grail?
As a mobile developer you most probably had to parse dates and maybe even consider different time zones and daylight saving times. Many apps still make use of java.util.Date, java.util.Calendar and java.text.SimpleDateFormat classes. These are legacy classes with a long history in the Java world, which were replaced with the Date and Time API (JSR-310) in Java 8.
Disclaimer: This article is not a tutorial on how to implement different Date / Time libraries. The goal is to compare the current options and give advice on which to choose.
Time to switch
If your minSDK is below 26 (Android 8.0) you can’t simply use Java 8 APIs. Since most apps probably have to support older Android versions for some years, I will show you current alternatives, their impact on dex count, APK size and other pros and cons.
Let’s meet the candidates
1. Java 6/7 Date API (e.g. java.util.Date, java.util.Calendar)
This is the legacy Java API available on all Android versions. Here is a short overview of some of the drawbacks and design problems of this API:
- Date is instant in time, doesn’t represent an actual date (no time zone, no format, no calendar system)
- Classes are mutable, no thread-safety, Calendar class is not type safe
- Unintuitive API (month is zero indexed, DayOfWeek != ISO 8601, lenient by default, implicit usage of the system-local)
There are more detailed articles about the issues of java.util.Date.
2. JodaTime (JodaTime Android)
JodaTime is a third-party replacement for the Java date and time classes and was the standard library for Java prior to JSR-310. There is a special Android variant of this library, which improves the timezone db loading. This library is only added to the list, because some apps still use it. You probably don’t want to use JodaTime in new projects.
3. ThreeTenBP (ThreeTenABP)
ThreeTen is a project within the Java Community Process program that integrates JSR-310 into Java and was included in Java 8 as java.time. There is a backport (BP) to allow developers on Java 7 to access an API that is mostly the same as the one in Java 8. There is also a special Android variant of this library which improves handling the timezone db (similar to JodaTime Android). Since the class names and API of ThreeTenBP is basically the same as Java 8 java.time you are able to switch between ThreeTenBP and java.time by just changing the imports.
This is the latest approach of Google to allow developers to access some of the Java 8 features (including the Date and Time API) even when using minSDK 25 or lower. By using Core Library Desugaring, the bytecode that the runtime needs to use certain Java 8 APIs is delivered as part of the APK (j$ package inside your dex file). If you reach minSDK 26 in the future you can simply remove the library desugaring to use the build-in Java 8 APIs.
The Kotlin team tries to make life easier for Kotlin and especially KMM developers. That’s why they are working on a basic Kotlin date/time library, with a convenient API and features like build in extension functions. We can use this in plain Android projects as well. kotlinx-datetime uses the java.time API internally on the JVM, so we need to enable core library desugaring to use it. The project is currently in an early development state (0.1.0) and doesn‘t comply with all ISO8601 standards. It’s also lacking formatting functionality.
Impact on the artifact
I created a simple open source sample app, using each library, to compare the impact on the final app artifact. The app has some basic use-cases like showing a countdown for next Sunday 19:00:00 Central European Time (CET) and parsing different ISO 8601 date strings.
As you can see from my comparison, core library desugaring has a noticeable footprint. There are several reasons. The desugaring process currently adds the Java 8 util.stream and util.concurrent packages to the APK (~3K methods) even if you don’t make use of it (D8/R8 doesn’t shrink them). There is an issue in the issue tracker about this. Also the desugaring relies on multidex, even if your total dexcount is below 64K. This slightly increases the APK size, so in the end the app is larger than with JodaTime or ThreeTenABP (even though these libraries ship their own timezone db).
Core library desugaring is a big step forward making our life as Android developers easier. We can finally use the Java 8 Date API and no longer need to rely on 3rd party libraries (even though they are really close to the language APIs). This also allows us to use kotlinx-datetime within KMM or Android only projects in the future.
The comparison also shows that the libraries have different impact on the final app size and method count. If you care about minimal size, it’s maybe worth to stick to ThreeTenABP for a little longer. Also migrating from ThreeTenABP to Java 8 later on is absolutely straightforward — as the API is the same and you just need to change your imports.