arjun
arjun

Reputation: 107

Convert UTC string date to date format

How to convert string "2020-09-02T12:22:53.9" to date format 2020-09-02T12:22:53.9 in java?

String dateString = "2020-09-02T12:22:53.9";
String tz = "America/Mexico_City";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-mm hh:mm:ss.S");
ZoneId zoneId = ZoneId.of(tz);
Instant instant = Instant.parse(dateString);
ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(dateTimeInTz.format(dtf));

This code throws a java.time.format.DateTimeParseException: Text '2020-09-02T12:22:53.9' could not be parsed at index 21 form the line Instant instant = Instant.parse(dateString);.

Upvotes: 0

Views: 1427

Answers (2)

Anonymous
Anonymous

Reputation: 86379

No formatter needed

I take it that your date string is in America/Mexico_City time zone and that you want output in the same time zone, so the same date and time. I further take it that internally in your program you want to represent the point in time as an Instant. The full circle from your date string to Instant and back may go:

    String tz = "America/Mexico_City";
    ZoneId zoneId = ZoneId.of(tz);
    
    String dateString = "2020-09-02T12:22:53.9";
    
    Instant instant = LocalDateTime.parse(dateString).atZone(zoneId).toInstant();
    System.out.println(instant);
    
    ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
    System.out.println(dateTimeInTz.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

Output:

2020-09-02T17:22:53.900Z
2020-09-02T12:22:53.9

Your input and your identical output are in ISO 8601 format. LocalDateTime parses ISO 8601 format without time zone or offset as its default, that is, without any explicit formatter. For printing the ZonedDateTime back in the same format, we are using the built-in DateTimeFormatter.ISO_LOCAL_DATE_TIME. As you may have realized by now, being free from specifying our own format pattern string is a great relief.

What went wrong in your code?

Arvind Kumar Avinash has already reported the errors in your format pattern string. More fundamentally, you cannot parse your string into an Instant, or more precisely, it takes something more to do that. The reason is that Java and the Instant class don’t know and cannot guess which time zone you intended. Your date string has date and time of day without any time zone. An Instant is a point in time, conceptually without any date or time of day. Your string could represent different points in time in different time zones, so only by specifying the time zone is it possible to determine the point in time.

What the Instant class can parse is a date and time in UTC denoted by a Z. An example of such a string is in the output from the Instant above, 2020-09-02T17:22:53.900Z. Since your string is not in UTC (and therefore hasn’t got the Z), this observation doesn’t help us in your case.

Link

Upvotes: 1

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79550

Your format is not correct. You have used mm, instead of MM, for the month. Also, you have missed the literal T in the format. Note that you need to use HH for 24-hours format time.

Since your date-time string does not have a time-zone information, you will have to parse the date-time string to LocalDateTime and then use LocalDateTime#atZone to convert it to ZonedDateTime (if at all you need ZonedDateTime) as shown below:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateString = "2020-09-02T12:22:53.9";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S");

        String tz = "America/Mexico_City";
        ZoneId zoneId = ZoneId.of(tz);

        // Parse the given date-time string to LocalDateTime
        LocalDateTime ldt = LocalDateTime.parse(dateString, dtf);

        // Convert the LocalDateTime to ZonedDateTime
        ZonedDateTime dateTimeInTz = ldt.atZone(zoneId);

        // Display ZonedDateTime in its default format
        System.out.println(dateTimeInTz);

        // Display ZonedDateTime in your custom format
        System.out.println(dateTimeInTz.format(dtf));
    }
}

Output:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9

Alternatively, you can use the ZoneId with DateTimeFormatter itself and then you can parse the given date-time string directly into ZonedDateTime as shown below:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateString = "2020-09-02T12:22:53.9";

        String tz = "America/Mexico_City";
        ZoneId zoneId = ZoneId.of(tz);

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S").withZone(ZoneId.of(tz));

        // Parse the given date-time string into ZonedDateTime
        ZonedDateTime dateTimeInTz = ZonedDateTime.parse(dateString, dtf);

        // Display ZonedDateTime in its default format
        System.out.println(dateTimeInTz);

        // Display ZonedDateTime in your custom format
        System.out.println(dateTimeInTz.format(dtf));
    }
}

Output:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9

Upvotes: 2

Related Questions