Convert UTC into Local Time on Android

Here's my attempt:

String dateStr = "Jul 16, 2013 12:08:59 AM";
SimpleDateFormat df = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss a", Locale.ENGLISH);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = df.parse(dateStr);
df.setTimeZone(TimeZone.getDefault());
String formattedDate = df.format(date);

Also notice the "a" for the am/pm marker...


I should like to contribute the modern answer. While SimpleDateFormat was the class we had for parsing and formatting date-times in 2013 (apart from Joda-Time), it is now long outdated, and we have so much better in java.time or JSR-310, the modern Java date and time API that came out with Java 8 in 2014.

But most Android devices still don’t run Java 8, I hear you say. Fortunately you can still use the modern Java date and time API on them through the ThreeTenABP, the backport of JSR-310 to Android Java 7. Details are in this question: How to use ThreeTenABP in Android Project.

Now the code is:

    DateTimeFormatter formatter 
            = DateTimeFormatter.ofPattern("MMM dd, uuuu hh:mm:ss a", Locale.ENGLISH);
    String aDate = "Jul 16, 2013 12:08:59 AM";
    String formattedDate = LocalDateTime.parse(aDate, formatter)
            .atOffset(ZoneOffset.UTC)
            .atZoneSameInstant(ZoneId.systemDefault())
            .format(formatter);
    System.out.println(formattedDate);

Since my computer is running Europe/Copenhagen time zone, which in July is 2 hours ahead of UTC, this prints

Jul 16, 2013 02:08:59 AM

Further points:

  • Since you have AM in your string, I assumed your hours are within AM, from 1 through 12. To parse and format them correctly you need lowercase h in the format pattern string. Uppercase H is for hour-of-day from 0 through 23.
  • Prefer to give an explcit locale to the formatter (whether SimpleDateFormat or DateTimeFormatter). If no locale is given, the formatter will use the device’s default locale. “Jul” and “AM” are in English, and your code may run nicely on many devices until one day it runs on a device with non-English locale and crashes, and you have a hard time figuring out why.
  • If you can, give the desired time zone explictly, for example as ZoneId.of("Asia/Kolkata"). The JVM’s default time zone may be changed by other parts of your program or other programs running in the same JVM, so is not reliable.