The Z
in the end means that the date/time is in UTC. When you put it inside quotes ('Z'
), you're saying to the formatter that it should be treated as a literal (the letter Z itself), ignoring the fact that it's in UTC - and the formatter will use the JVM default timezone instead.
Another detail is that your input has 6 decimal digits for the fraction of seconds:
2018-04-04T08:41:21.265185Z
Unfortunately, SimpleDateFormat
can handle only 3 decimal digits. With more than 3 digits, it gives wrong results.
One alternative is to discard the extra digits, leaving only 3. Then you use another formatter to get the output (better than substring
it):
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
String input = "2018-04-04T08:41:21.265185Z";
// keep only 3 decimal digits, ignore the rest
input = input.replaceAll("(\\.\\d{3})\\d*", "$1"); // input is now "2018-04-04T08:41:21.265Z"
// parse it
Date date = dateFormat.parse(input);
SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm");
outputFormat.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
// convert the UTC date to another timezone
String finalTime = outputFormat.format(date); // 14:11
This converts the UTC's time (08:41) to India's timezone (14:11) - that's what I understood from your question that you're trying to do.
For the timezone name, I used "Asia/Kolkata". Abbreviations such as "IST" are ambiguous and the API usually doesn't do what you need (IST is used in Israel, Ireland and India, and who knows what the API considers to be the default).
To parse all the 6 fractional digits, the only way is to use another API. In Android you can use ThreetenABP, or java.time
classes in API level 26:
Instant instant = Instant.parse("2018-04-04T08:41:21.265185Z");
String finalTime = instant
// convert to another timezone
.atZone(ZoneId.of("Asia/Kolkata"))
// format (just hour and minutes) -> 14:11
.format(DateTimeFormatter.ofPattern("HH:mm"));