0

I am trying to convert UTC to time local,

Below is the code which I am using,

public static String utcToLocalDateFormat(String dateString) {

        Log.i("DateFormat", "utcToLocal:Before===>" + dateString);

        String formattedDate = null;
        if (dateString != null) {
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            dateFormat.setTimeZone(TimeZone.getDefault());
            Date date = null;
            try {

                Log.i("DateFormat", "getTimeZone===>" +dateFormat.getTimeZone());
                date = dateFormat.parse(dateString);
                System.out.println(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            formattedDate = dateFormat.format(date);
            Log.i("DateFormat", "utcToLocal:After===>" + formattedDate);

        }
        return formattedDate;
    }

But problem is before and after timezone conversion time is same.Its not converting to UTC to Local time. Any help appreciated.

Following are my input: 1)2017-08-31 20:40:59 2)2017-09-01 11:16:24.024

Following is output: 1)2017-08-31 20:40:59 2)2017-09-01 11:16:24

Joe
  • 550
  • 2
  • 11
  • 21
  • 1
    Could you please provide some inputs and outputs (expected vs what you're getting)? –  Sep 01 '17 at 12:25
  • 1
    Is it OK that your `dateFormat` parses the input as the local TZ? – yegodm Sep 01 '17 at 12:30
  • In your date format pattern you have no information in what timezone it will be passed to your method. So the string is parsed as it is already in default time zone. – Damian0o Sep 01 '17 at 12:38
  • Set the dateFormat’s time zone to UTC before parsing to obtain correct UTC time. Then set it to your local time zone before formatting. – Ole V.V. Sep 01 '17 at 12:39
  • A similar question has been asked many times. I wonder whether you could have found the answer faster through for instance [Java Convert GMT/UTC to Local time doesn't work as expected](https://stackoverflow.com/questions/19375357/java-convert-gmt-utc-to-local-time-doesnt-work-as-expected) or [Java: How do you convert a UTC timestamp to local time?](https://stackoverflow.com/questions/12487125/java-how-do-you-convert-a-utc-timestamp-to-local-time). Thank through posting your own question. – Ole V.V. Sep 01 '17 at 12:49

2 Answers2

2

When you do:

dateFormat.setTimeZone(TimeZone.getDefault());

And then parse the String, you're saying to the formatter: "I'm gonna give you a String with a date and time in this timezone". As you used TimeZone.getDefault(), it'll use the JVM's default timezone. So the first thing is to tell the formatter to use UTC when parsing:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use UTC to parse
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
....
date = dateFormat.parse(dateString);

I'm testing with dateString equals to 2017-08-01 10:00:00. So, the date will be equivalent to 2017-08-01 10:00:00 UTC. When you print the date with System.out.println, it'll call the toString() and convert it to the JVM's default timezone.

In the JVM I'm using, the default timezone is America/Sao_Paulo, so when I call this:

System.out.println(date);

It prints:

Tue Aug 01 07:00:00 BRT 2017

Because in August 1st, 10 AM in UTC is equivalent to 7 AM in São Paulo. This will result will change according to your JVM's default timezone.

If you want to print this date but with the date and time equivalent to another timezone (other than UTC), you'll need another formatter with a different timezone set:

DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use my default timezone to format (America/Sao_Paulo)
dateFormat2.setTimeZone(TimeZone.getDefault());
formattedDate = dateFormat2.format(date);

This will print:

2017-08-01 07:00:00

Instead of the default timezone, you can use whatever timezone you want (I'm using America/New_York as an example):

DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use New York timezone
dateFormat2.setTimeZone(TimeZone.getTimeZone("America/New_York"));
formattedDate = dateFormat2.format(date);

This will convert the date/time to New York's timezone:

2017-08-01 06:00:00

If you want to print the date/time in UTC, then you don't need to create another formatter, just use the first one (as it's already set to UTC).


The JVM's default timezone can be changed without notice, even at runtime, so it's better to use a specific one instead of just using getDefault().

Prefer to use IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin). Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.

You can get a list of available timezones (and choose the one that fits best your system) by calling TimeZone.getAvailableIDs().


New Date/Time API

The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.

In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).

This API is much easier to work with. First you create a org.threeten.bp.format.DateTimeFormatter and parse the input String to a org.threeten.bp.LocalDateTime.

Then you convert it to UTC (creating a org.threeten.bp.ZonedDateTime), and then to the timezone you want, and use another formatter to output it:

// date/time with optional milliseconds
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]");
// parse to LocalDateTime
LocalDateTime dt = LocalDateTime.parse(dateString, parser);

// convert to UTC
ZonedDateTime z = dt.atZone(ZoneOffset.UTC);

// convert to another timezone
z = z.withZoneSameInstant(ZoneId.of("America/New_York"));
// format it
// date/time without milliseconds
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(z));

You can also use the default timezone using ZoneId.systemDefault(), and get all the available timezones with ZoneId.getAvailableZoneIds().

If you want the date/time in UTC, you can skip the call to withZoneSameInstant().


To convert it to a java.util.Date, you can use the org.threeten.bp.DateTimeUtils class:

// convert ZonedDateTime to java.util.Date
Date d = DateTimeUtils.toDate(z.toInstant());
  • Thanks,But I dont want specify time zone like (TimeZone.getTimeZone("America/New_York")) what you mentioned, My application used any part of world it should work according that timezone. – Joe Sep 01 '17 at 13:05
  • @Joe I've updated the answer to make it more clear. –  Sep 01 '17 at 13:11
0

Change the line

dateFormat.setTimeZone(TimeZone.getDefault());

to

dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Damian0o
  • 653
  • 5
  • 15