-2

i wrote an util function to convert a string time value of format 2018-11-26T15:12:03.000-0800 to localdatetime of format "M/dd/yy HH:mm:ss a z"

string of format 2018-11-26T15:12:03.000-0800 to java.time.localdatetime of format "M/dd/yy HH:mm:ss a z" conversion throwing exception.

public static LocalDateTime convertStringToTime(String time){
    String pattern = "M/dd/yy HH:mm z";
    DateTimeFormatter formatter =  DateTimeFormatter.ofPattern(pattern);
    ZonedDateTime zonedDateTime = ZonedDateTime.parse(time,formatter);
    return zonedDateTime.toLocalDateTime();
}

which gives me the below exception

java.time.format.DateTimeParseException: Text '2018-11-26T12:45:23.000-0800' could not be parsed at index 4
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Akhil
  • 1
  • 1
  • 1
    Okay, how does `2018-11-26T15:12:03.000-0800` match `M/dd/yy HH:mm z`? I would also spend a lot less time "caring" about the format and simply allowing the database/jdbc driver to deal with, as you should not be storing dates in the database as `String`s – MadProgrammer Dec 10 '18 at 22:06
  • so i want to convert the string of format "2018-11-26T15:12:03.000-0800" to local date time of format "M/dd/yy HH:mm z" – Akhil Dec 10 '18 at 22:09
  • 1
    Many of the new JDBC drivers allows you to things like `LocalDate localDate = rs.getObject(1, LocalDate.class));`, but you will have to consult your databases driver's documentation. Or, failing that support, you "can" convert a `Local/ZonedDateTime` to a `java.sql.Date` object and simply use that - it's messy, but far better then trying to deal with string manipulation – MadProgrammer Dec 10 '18 at 22:10
  • 1
    Yes, I understand what you "want" to do, but I'm trying to tell you that it's not the best approach. This kind of data should never be managed as plain text, but instead should be managed as "object" data. Since most database support date/time types, you should take advantage of this support as much as you can. Also understand then when "parsing" date/time value, the pattern MUST match in the coming values format – MadProgrammer Dec 10 '18 at 22:12
  • A `LocalDateTime` doesn’t (as in cannot have) a format. Possibly partially a duplicate of [https://stackoverflow.com/questions/50462041/localdate-format-format-is-not-applied](https://stackoverflow.com/questions/50462041/localdate-format-format-is-not-applied). Also apparently related to [Convert String Date to String date different format](https://stackoverflow.com/questions/14999506/convert-string-date-to-string-date-different-format). – Ole V.V. Dec 11 '18 at 09:35

1 Answers1

0

You say that you want: a LocalDateTime of format M/dd/yy HH:mm:ss a z. This is impossible for three reasons:

  1. A LocalDateTime cannot have a format. Its toString method always returns a string like 2018-11-26T15:12:03 (ISO 8601 format), there is no way we can change that. You also shouldn’t want a LocalDateTime with a specific format; I include a link at the bottom explaining why not.
  2. I assume that by z in your format you mean time zone abbreviation like PDT for Pacific Daylight Time. A LocalDateTime neither has UTC offset not time zone, so this doesn’t make sense.
  3. Your input time string doesn’t hold any time zone either, only an offset from UTC. So to print a time zone abbreviation, you will first need to choose a time zone.

Instead I suggest:

    ZoneId zone = ZoneId.of("America/Whitehorse");
    DateTimeFormatter inputFormatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXX");
    DateTimeFormatter desiredFormatter
            = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.LONG)
                    .withLocale(Locale.US);

    String time = "2018-11-26T15:12:03.000-0800";
    OffsetDateTime dateTime = OffsetDateTime.parse(time, inputFormatter);
    String formattedDateTime = dateTime.atZoneSameInstant(zone)
            .format(desiredFormatter);

    System.out.println("Converted format: " + formattedDateTime);

Output is:

Converted format: 11/26/18, 3:12:03 PM PST

To convert date and time from a string in one format to a string in another format you generally need two DateTimeFormatters: one specifying the format of the string you’ve got and one specifying the format that you want.

Rather than building your own formatter from a format pattern string, rely on built-in formats when you can. In our case I specify FormatStyle.SHORT for the date (giving two-digit-year) and FormatStyle.LONG for the time, giving us the time zone abbreviation.

The idea of relying on built-in formats can be taken one step further. The string you’ve got is in ISO 8601 format, so we just need to piece two pieces together:

    DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .appendOffset("+HHmm", "Z")
            .toFormatter();

It’s longer, but it’s less error-prone.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161