By kael

2016-08-12 16:36:26 8 Comments

I'm adding this question because I'm new to Java and Android and I searched for hours trying to figure this out. The answer came from a combination of related answers, so I figured I'd document what I learned for anyone else who may be struggling. See answer.

For a bit of background, my experience is mostly web development in PHP and a little bit of Ruby. My only OS is Linux (Ubuntu Studio), and I'm (begrudgingly) developing my first Android app in Android Studio 2.1.2. My Java setup is the following:

>java -version
> openjdk version "1.8.0_91"
> OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-3ubuntu1~15.10.1-b14)
> OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)


@eLi 2018-11-01 10:15:02

This Solution Covers all the ThreeTenABP from installation to use.

The Open Event Android project helps event organizers to organize the event and generate Apps (apk format) for their events/conferences by providing API endpoint or zip generated using Open Event server. For any Event App it is very important that it handles time zone properly. In Open Event Android App there is an option to change time zone setting. The user can view date and time of the event and sessions in Event Timezone and Local time zone in the App. ThreeTenABP provides a backport of the Java SE 8 date-time classes to Java SE 6 and 7. In this blog post I explain how to use ThreeTenABP for time zone handling in Android.

1. Add dependency

To use ThreeTenABP in your application you have to add the dependency in your app module’s build.gradle file.

dependencies {
      compile    'com.jakewharton.threetenabp:threetenabp:1.0.5'
      testCompile   'org.threeten:threetenbp:1.3.6'

2. Initialize ThreeTenABP
Now in the onCreate() method of the Application class initialize ThreeTenABP.


3. Create getZoneId() method
Firstly create getZoneId() method which will return ZoneId according to user preference. This method will be used for formatting and parsing dates Here showLocal is user preference. If showLocal is true then this function will return Default local ZoneId otherwise ZoneId of the Event.

private static ZoneId geZoneId() {
        if (showLocal || Utils.isEmpty(getEventTimeZone()))
            return ZoneId.systemDefault();
            return ZoneId.of(getEventTimeZone());

Here getEventTimeZone() method returns time zone string of the Event.

ThreeTenABP has mainly two classes representing date and time both.
- ZonedDateTime : ‘2011-12-03T10:15:30+01:00[Europe/Paris]’
- LocalDateTime : ‘2011-12-03T10:15:30’

ZonedDateTime contains timezone information at the end. LocalDateTime doesn’t contain timezone.

4. Create method for parsing and formating
Now create getDate() method which will take isoDateString and will return ZonedDateTime object.

public static ZonedDateTime getDate(@NonNull String isoDateString) {
        return ZonedDateTime.parse(isoDateString).withZoneSameInstant(getZoneId());;

Create formatDate() method which takes two arguments first is format string and second is isoDateString. This method will return a formatted string.

public static String formatDate(@NonNull String format, @NonNull String isoDateString) {
        return DateTimeFormatter.ofPattern(format).format(getDate(isoDateString));

String isoDateString = "2017-11-09T23:08:56+08:00";

ZonedDateTime dateInEventTimeZone = DateConverter.getDate(isoDateString);

dateInEventTimeZone.toString();  //2017-11-09T23:08:56+08:00[Asia/Singapore]

ZonedDateTime dateInLocalTimeZone = DateConverter.getDate(dateInLocalTimeZone);

dateInLocalTimeZone.toString();  //2017-11-09T20:38:56+05:30[Asia/Kolkata]


String date = "2017-03-17T14:00:00+08:00";
String formattedString = formatDate("dd MM YYYY hh:mm:ss a", date));

formattedString // "17 03 2017 02:00:00 PM"


@kael 2016-08-12 16:36:26

First Discovery: Why You Have To Use ThreeTenABP Instead of java.time, ThreeTen-Backport, or even Joda-Time

This is a really short version of the VERY LONG PROCESS of defining a new standard. All of these packages are pretty much the same thing: libraries that provide good, modern time handling functionality for Java. The differences are subtle but important.

The most obvious solution would be to use the built-in java.time package, since this is the new standard way to deal with time and dates in Java. It is an implementation of JSR 310, which was a new standard proposal for time handling based on the Joda-Time library.

However, java.time was introduced in Java 8. Android up to Marshmallow runs on Java 7 ("Android N" is the first version to introduce Java 8 language features). Thus, unless you're only targeting Android N Nougat and above, you can't rely on Java 8 language features (I'm not actually sure this is 100% true, but this is how I understand it). So java.time is out.

The next option might be Joda-Time, since JSR 310 was based on Joda-Time. However, as the ThreeTenABP readme indicates, for a number of reasons, Joda-Time is not the best option.

Next is ThreeTen-Backport, which back-ports much (but not all) of the Java 8 java.time functionality to Java 7. This is fine for most use cases, but, as indicated in the ThreeTenABP readme, it has performance issues with Android.

So the last and seemingly correct option is ThreeTenABP.

Second Discovery: Build Tools and Dependency Management

Since compiling a program -- especially one using a bunch of external libraries -- is complex, Java almost invariably uses a "build tool" to manage the process. Make, Apache Ant, Apache Maven, and Gradle are all build tools that are used with Java programs (see this post for comparisons). As noted further down, Gradle is the chosen build tool for Android projects.

These build tools include dependency management. Apache Maven appears to be the first to include a centralized package repository. Maven introduced the Maven Central Repository, which allows functionality equivalent to php's composer with Packagist and Ruby's gem with In other words, the Maven Central Repository is to Maven (and Gradle) what Packagist is to composer -- a definitive and secure source for versioned packages.

Third Discovery: Gradle Handles Dependencies in Android Projects

High on my to-do list is to read the Gradle docs here, including their free eBooks. Had I read these weeks ago when I started learning Android, I would surely have known that Gradle can use the Maven Central Repository to manage dependencies in Android Projects. Furthermore, as detailed in this StackOverflow answer, as of Android Studio 0.8.9, Gradle uses Maven Central Repository implicitly through Bintray's JCenter, which means you don't have to do any extra config to set up the repo -- you just list the dependencies.

Fourth Discovery: Project Dependencies Are Listed in [project dir]/app/build.gradle

Again, obvious to those who have any experience using Gradle in Java, but it took me a while to figure this out. If you see people saying "Oh, just add compile 'this-or-that.jar'" or something similar, know that compile is a directive in that build.gradle file that indicates compile-time dependencies. Here's the official Gradle page on dependency management.

Fifth Discovery: ThreeTenABP Is Managed by Jake Wharton, not by ThreeTen

Yet another issue I spent too much time figuring out. If you look for ThreeTen in Maven Central, you'll only see packages for threetenbp, not threetenabp. If you go to the github repo for ThreeTenABP, you'll see that infamous compile 'this-or-that' line under the Download section of the Readme.

When I first hit this github repo, I didn't know what that compile line meant, and I tried to run it in my terminal (with an obvious and predictable failure). Frustrated, I didn't return to it until long after I figured the rest out, and finally realized that it's a Maven Repo line pointing to the com.jakewharton.threetenabp repo, as opposed to the org.threeten repo. That's why I thought the ThreeTenABP package wasn't in the Maven repo.

Summary: Making it work

Now it all seems pretty easy. You can get modern time handling functions in an Android project by making sure your [project folder]/app/build.gradle file has the compile 'com.jakewharton.threetenabp:threetenabp:1.0.3' line in its dependencies section:

apply plugin: ''

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "me.ahuman.myapp"
        minSdkVersion 11
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), ''

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation 'junit:junit:4.12'
    implementation ''
    implementation ''
    implementation 'com.jakewharton.threetenabp:threetenabp:1.0.3'

@Bob 2017-08-26 14:34:45

Thanks for the great post. However, I wonder whether you have considered JodaTimeAndroid as well.

@kael 2017-08-29 16:19:58

@Bob, I haven't experimented with JodaTimeAndroid, but only because I'm not really working on anything right now that requires it. From what I remember, the java.time implementation was fine (being basically a port of JodaTime), and I'm sure that in another year or two, 90% of users will be on Nougat+, making it a viable solution for development.

@M. Prokhorov 2017-11-28 10:41:46

@Bob, JodaTime is basically the same as JSR-310 (even basically made by the same guys), except JSR-310 supposedly has fewer design flaws (see this article, for example). [...continued below]

@M. Prokhorov 2017-11-28 10:42:14

@Bob, from my experience in using both libraries, I wouldn't say that I agree with everything made different in JSR-310 compared to Joda (for example, how it distincts "human" time and "machine" time in basically completely different API branches, which makes it annoying when you need to interface with legacy API, as most of them considered "machine", yet majority of logic requires them to be worked with as if they are "human"). But I certainly see why and how these decisions were made, and JSR-310 is certainly more extensible (speaking from experience of writing my own Chronology).

@Basil Bourque 2018-01-14 07:05:11

To clarify the comments… The java.time framework (JSR 310) is the official successor to the Joda-Time project. Both projects are led by the same man, Stephen Colebourne. The Joda-Time project is now in maintenance mode, with the team advising migration to java.time.

@Travis Griggs 2018-07-19 23:51:54

Of late, you have to change that line to be implementation 'com.jakewharton.threetenabp:threetenabp:1.0.3'

@Ole V.V. 2018-10-09 03:12:39

Make sure you call AndroidThreeTen.init(this) before using the API, for example in onCreate().See ThreeTen-Backport error on Android - ZoneRulesException: No time-zone data files registered.

Related Questions

Sponsored Content

87 Answered Questions

[SOLVED] Close/hide the Android Soft Keyboard

26 Answered Questions

20 Answered Questions

[SOLVED] What is Gradle in Android Studio?

89 Answered Questions

[SOLVED] "cannot resolve symbol R" in Android Studio

41 Answered Questions

[SOLVED] Is there a unique Android device ID?

13 Answered Questions

[SOLVED] Proper use cases for Android UserManager.isUserAGoat()?

25 Answered Questions

[SOLVED] Is there a way to run Python on Android?

77 Answered Questions

30 Answered Questions

[SOLVED] Android Studio is slow (how to speed up)?

8 Answered Questions

[SOLVED] 'android-24' requires JDK 1.8 or later to compile

Sponsored Content