0

I have a date String like 2017-09-16T05:06:18.157 and I want to convert it to local time (IST). In Indian Standard Time it will be around 2017-09-16 10:36:18.

With Joda-Time, I have tried to convert it to local but I was not able to do it.

Below is my code:

private String getConvertDate(String date_server) {
    DateTimeFormatter inputFormatter = DateTimeFormat
            .forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
            .withLocale(Locale.US);

    DateTime parsed = inputFormatter.parseDateTime(date_server);

    DateTimeFormatter outputFormatter = DateTimeFormat
            .forPattern("yyyy-MM-dd HH:mm:ss")
            .withLocale(Locale.US)
            .withZone(DateTimeZone.getDefault());

    return outputFormatter.print(parsed);
}
Reva
  • 59
  • 1
  • 1
  • 7
  • Welcome to Stack Overflow. Please note that Stack Overflow is no substitute for your search engine. This question has been asked answered many times, and your search engine would have found your answer much faster. – Ole V.V. Sep 16 '17 at 07:06
  • 1
    Joda-Time is (from all I know) better than the outdated `SimpleDateFormat` used in the answers posted this far. Best is [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP). – Ole V.V. Sep 16 '17 at 07:07
  • 1
    Your timestamp string conforms with ISO 8601, the format that I believe that Joda-Time and certainly ThreeTenABP understands as their default, so you don’t need an explicit formatter for parsing. – Ole V.V. Sep 16 '17 at 07:16
  • 1
    ThreeTenABP solution: `LocalDateTime.parse("2017-09-16T05:06:18.157") .atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.of("Asia/Kolkata")) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.US))` – Ole V.V. Sep 16 '17 at 07:23
  • **ThreeTenABP** backports the modern and much nicer Java date and time API to Android Java 7. How to use, see [this question: How to use ThreeTenABP in Android Project](https://stackoverflow.com/questions/38922754/how-to-use-threetenabp-in-android-project). – Ole V.V. Sep 16 '17 at 07:25

3 Answers3

6

Good you found a solution with SimpleDateFormat. I'd just like to add more insights about it (basically because the old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs).

The input String (2017-09-16T05:06:18.157) contains only the date (year/month/day) and time (hour/minute/second/millisecond), but no timezone information. So, when calling parseDateTime, Joda-Time just assumes that it's in the JVM default timezone.

If you know that the input is in UTC, but the input itself has no information about it, you must tell it. One way is to set in the formatter:

// set the formatter to UTC
DateTimeFormatter inputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
    .withZone(DateTimeZone.UTC);

// DateTime will be in UTC
DateTime parsed = inputFormatter.parseDateTime("2017-09-16T05:06:18.157");

Another alternative is to first parse the input to a org.joda.time.LocalDateTime (a class that represents a date and time without a timezone), and then convert it to a DateTime in UTC:

// parse to LocalDateTime
DateTime = parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
    // convert to a DateTime in UTC
    .toDateTime(DateTimeZone.UTC);

Both produces the same DateTime, corresponding to UTC 2017-09-16T05:06:18.157Z.

To format it to "IST timezone" (which is actually not a timezone - more on that below), you can also set the timezone in the formatter:

// convert to Asia/Kolkata
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    .withZone(DateTimeZone.forID("Asia/Kolkata"));
System.out.println(outputFormatter.print(parsed));

Or you can convert the DateTime to another timezone, using the withZone() method:

DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
// convert to Asia/Kolkata
System.out.println(outputFormatter.print(parsed.withZone(DateTimeZone.forID("Asia/Kolkata"))));

Both will print:

2017-09-16 10:36:18

In your code you're using DateTimeZone.getDefault(), that gets the JVM default timezone (with some tricky details). But the default timezone can be changed without notice, even at runtime, so it's always better to specify which one you want to use.

Also, keep in mind that short names like IST are not real timezones. Always prefer to use IANA timezones names (always in the format Region/City, like Asia/Kolkata or Europe/Berlin).

Avoid using the 3-letter abbreviations (like IST or PST) because they are ambiguous and not standard. Just check in this list that IST can be "India Standard Time", "Israel Standard Time" and "Irish Standard Time".

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


Java new Date/Time API

Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".

If you can't (or don't want to) migrate from Joda-Time to the new API, you can ignore this section.

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 new API has lots of different date/time types for each situation.

First, you can parse the input to a org.threeten.bp.LocalDateTime, then I use a org.threeten.bp.ZoneOffset to convert it to UTC, resulting in a org.threeten.bp.OffsetDateTime.

Then, I use a org.threeten.bp.ZoneId to convert this to another timezone, and use a org.threeten.bp.format.DateTimeFormatter to format it (this is basically what's suggested by @Ole V.V's comment - just to show how straightforward it is, as there aren't anything much different to do):

// parse to LocalDateTime
OffsetDateTime parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
    // convert to UTC
    .atOffset(ZoneOffset.UTC);

// convert to Asia/Kolkata
ZoneId zone = ZoneId.of("Asia/Kolkata");
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(outputFormatter.format(parsed.atZoneSameInstant(zone)));

The output is:

2017-09-16 10:36:18

3

try this code:

   String serverdateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";

  public String convertServerDateToUserTimeZone(String serverDate) {
    String ourdate;
    try {
        SimpleDateFormat formatter = new SimpleDateFormat(serverdateFormat, Locale.UK);
        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date value = formatter.parse(serverDate);
        TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
        SimpleDateFormat dateFormatter = new SimpleDateFormat(serverdateFormat, Locale.UK); //this format changeable
        dateFormatter.setTimeZone(timeZone);
        ourdate = dateFormatter.format(value);

        //Log.d("OurDate", OurDate);
    } catch (Exception e) {
        ourdate = "0000-00-00 00:00:00";
    }
    return ourdate;
}
Vishal Thakkar
  • 2,117
  • 2
  • 16
  • 33
  • 3
    Please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat`. From Joda-Time used in the questions this is surely a step *backward*. – Ole V.V. Sep 16 '17 at 07:26
0
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone utcZone = TimeZone.getTimeZone("UTC");
simpleDateFormat.setTimeZone(utcZone);
Date myDate =simpleDateFormat.parse(rawQuestion.getString("Asia/Kolkata"));

simpleDateFormat.setTimeZone(TimeZone.getDefault());
String formattedDate = simpleDateFormat.format(myDate);
Harshit Trivedi
  • 764
  • 9
  • 33
  • 2
    Not working. I have put my mentioned date and its giving me 9/16/17 5:06 AM +0530. – Reva Sep 16 '17 at 05:36
  • 1
    Please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat`. From Joda-Time used in the questions this is surely a step *backward*. – Ole V.V. Sep 16 '17 at 07:26