kushi
kushi

Reputation: 77

yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z' format

I am trying to convert GMT to IST.

  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS");
  Date c= sdf.parse("2017-03-31T10:38:14.4723017Z");

  Date date = new Date();
  DateFormat istFormat = new SimpleDateFormat();
  DateFormat gmtFormat = new SimpleDateFormat();
  TimeZone gmtTime = TimeZone.getTimeZone("GMT");
  TimeZone istTime = TimeZone.getTimeZone("IST");

  istFormat.setTimeZone(gmtTime);
  gmtFormat.setTimeZone(istTime);
  System.out.println("GMT Time: " + istFormat.format(c));
  System.out.println("IST Time: " + gmtFormat.format(c));

My output is

GMT Time: 31/3/17 6:26 AM
IST Time: 31/3/17 11:56 AM

But my actual output should be

GMT Time: 31/3/17 5:08 AM
IST Time: 31/3/17 10:38 AM

What is wrong with my code?

Upvotes: 3

Views: 22721

Answers (4)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79560

Some important points first

  1. Avoid using abbreviations for time zone ID. Given below is an excerpt from the legacy TimeZone documentation:

Three-letter time zone IDs

For compatibility with JDK 1.1.x, some other three-letter time zone IDs (such as "PST", "CTT", "AST") are also supported. However, their use is deprecated because the same abbreviation is often used for multiple time zones (for example, "CST" could be U.S. "Central Standard Time" and "China Standard Time"), and the Java platform can then only recognize one of them.

  1. The error-prone SimpleDateFormat processes the number of decimal points as the milliseconds. 4723017 milliseconds = 1 hour 18 minutes 43.017S which explains the difference in your output.
   System.out.println(Duration.ofMillis(4723017)); // PT1H18M43.017S

java.time

In March 2014, Java 8 introduced the modern, java.time date-time API which supplanted the error-prone legacy java.util date-time API. Any new code should use the java.time API.

Solution using modern date-time API

Your given date-time string is in the ISO 8601 format, the default format used by java.time types. So, you do not need to use a DateTimeFormatter explicitly to parse it into an Instant or a ZonedDateTime or an OffsetDateTime e.g.

Instant instant = Instant.parse("2017-03-31T10:38:14.4723017Z");
ZonedDateTime zdt = ZonedDateTime.parse("2017-03-31T10:38:14.4723017Z");
OffsetDateTime odt = OffsetDateTime.parse("2017-03-31T10:38:14.4723017Z");

Note that Z represents a time zone offset of +00:00 i.e. zero offset from UTC or GMT. I have parsed your date-time string into an Instant and converted it into a ZonedDateTime at ZoneId.of("Asia/Kolkata").

Demo:

class Main {
    public static void main(String args[]) {
        Instant instant = Instant.parse("2017-03-31T10:38:14.4723017Z");
        System.out.println(instant);

        ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Kolkata"));
        System.out.println(zdt);

        // Representation in a custom format
        System.out.println(zdt.format(
                DateTimeFormatter.ofPattern("M/d/uu h:mm a VV", Locale.ENGLISH)
        ));
    }
}

Output:

2017-03-31T10:38:14.472301700Z
2017-03-31T16:08:14.472301700+05:30[Asia/Kolkata]
3/31/17 4:08 PM Asia/Kolkata

Online Demo

Learn more about the modern Date-Time API from Trail: Date Time.

Upvotes: 1

Mikhail Yaskou
Mikhail Yaskou

Reputation: 89

Try use this format "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZ"

Upvotes: -1

Riaan Nel
Riaan Nel

Reputation: 2535

Milliseconds (SSS) can only be three digits. On more than that, the date rolls over - e.g. 10:38:14.1000 becomes 10:38:15.000. Add a couple of million milliseconds... and you get the behaviour that you're seeing now.

Try this.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Date c = sdf.parse("2017-03-31T10:38:14.472Z");

System.out.println(c);

DateFormat istFormat = new SimpleDateFormat();
DateFormat gmtFormat = new SimpleDateFormat();
TimeZone gmtTime = TimeZone.getTimeZone("GMT");
TimeZone istTime = TimeZone.getTimeZone("IST");

istFormat.setTimeZone(gmtTime);
gmtFormat.setTimeZone(istTime);
System.out.println("GMT Time: " + istFormat.format(c));
System.out.println("IST Time: " + gmtFormat.format(c));

Upvotes: 6

Urko Pineda
Urko Pineda

Reputation: 132

Have you tried changing the format to "yyyy-MM-dd'T'HH:mm:ss.sssssssZ"?

Also, when you type Z in your Date object, you should write the time zone designator, for example, "2017-03-31T10:38:14.4723017+01:00".

Upvotes: -1

Related Questions