How to generate TimeFormatter in YYYY-mm-DDThh format: mm: ss-TZ

3

I have the string 2018-09-26T10:36:40-03:00 and would like to convert it to LocalDateTime .

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

LocalDate.parse("2018-09-26T10:36:40-03:00",formatter)
    
asked by anonymous 24.10.2018 / 15:38

1 answer

2

java.time classes already parsing strings in the ISO 8601 format , which is the format in which the your string is.

You said you want LocalDateTime , but in your code you're using LocalDate . Either way, you can get both.

Your string has date ( 2018-09-26 ), time ( 10:36:40 ) and offset ( -03:00 ), so the best type to represent it is OffsetDateTime .

From OffsetDateTime you can get LocalDateTime and LocalDate :

OffsetDateTime odt = OffsetDateTime.parse("2018-09-26T10:36:40-03:00");
LocalDateTime datetime = odt.toLocalDateTime();
LocalDate date = odt.toLocalDate();

Your code did not work because the format passed to DateTimeFormatter does not match the input string.

The% wrapper, for example, represents the day, followed by dash, followed by the month, dash, and year, but the string begins with the 4-digit year (see documentation for all the letters that can be used and what each one means). Not counting the dd-MM-yyyy (in single quotation marks), which corresponds to the actual letter "Z" (and not to a specific date field).

If you want to use 'Z' , you can parse directly to DateTimeFormatter or LocalDate , without needing LocalDateTime :

String str = "2018-09-26T10:36:40-03:00";
LocalDateTime datetime = LocalDateTime.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
LocalDate date = LocalDate.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME);

Note that the API already has OffsetDateTime ready to parse the format you have ( DateTimeFormatter ).

Just as a curiosity, you can also build your own DateTimeFormatter.ISO_OFFSET_DATE_TIME :

DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX");
String str = "2018-09-26T10:36:40-03:00";
LocalDateTime datetime = LocalDateTime.parse(str, parser);
LocalDate date = LocalDate.parse(str, parser);

The difference is that DateTimeFormatter is more flexible, because it also parses if the string has fractions of a second, while DateTimeFormatter.ISO_OFFSET_DATE_TIME above only accepts strings in the specified format.

Note that I used parser instead of u for the year because y does not work for AC (BC) dates. Since y works for both cases (AC and DC), it is the best choice (and this field is the same as u , by the way). See this SOen response to better understand the details.

Another difference is that DateTimeFormatter.ISO_OFFSET_DATE_TIME does not accept invalid dates like April 31 (because this month only has 30 days) and February 29 in non-leap years. Already using DateTimeFormatter.ISO_OFFSET_DATE_TIME , the default is to accept these dates (and make some strange adjustments). See this answer for more details on this behavior.

Just to give an example:

DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX");
// 31 de abril
String str = "2018-04-31T10:36:40-03:00";
System.out.println(LocalDate.parse(str, parser)); // 2018-04-30
System.out.println(LocalDate.parse(str, DateTimeFormatter.ISO_OFFSET_DATE_TIME)); // DateTimeParseException

Using ofPattern , ofPattern returned accepts April 31, setting it to April 30. DateTimeFormatter throws DateTimeFormatter.ISO_OFFSET_DATE_TIME because the date is invalid.

To use DateTimeParseException and not accept invalid dates, simply use the suggested solution in this answer :

DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX")
    .withResolverStyle(ResolverStyle.STRICT);

Using ofPattern , ResolverStyle.STRICT will only accept valid dates.

    
24.10.2018 / 15:53