How to generate Timeformatter in YYYY-mm-Ddthh:mm:ss-TZ format

Asked

Viewed 2,159 times

3

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

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

LocalDate.parse("2018-09-26T10:36:40-03:00",formatter)

1 answer

2


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

You said you want one LocalDateTime, but in your code you’re using LocalDate. Either way, it is possible to get both.

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

From the OffsetDateTime you can get the LocalDateTime and the LocalDate:

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

Your code didn’t work because the format passed to the DateTimeFormatter does not match the input string.

The excerpt dd-MM-yyyy, for example, represents the day, followed by dash, followed by the month, stroke and year, but the string starts with the 4 digits of the year (see documentation to know all the letters that can be used and what each one means). Not counting the 'Z' (between single quotes), which corresponds to the letter "Z" itself (and not to a date-specific field).


If you want to use a DateTimeFormatter, it is possible to do Parsing directly to LocalDate or LocalDateTime, without needing the OffsetDateTime:

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 one DateTimeFormatter ready to make Parsing of the format you have (DateTimeFormatter.ISO_OFFSET_DATE_TIME).


Just as curiosity, it is also possible to build your own DateTimeFormatter:

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 the DateTimeFormatter.ISO_OFFSET_DATE_TIME is more flexible as it also does Parsing if the string has the fractions of a second, while the parser above only accepts strings in the specified format.

Note that I used u instead of y next year, as the y does not work for AC (Before Christ) dates. How u works for both cases (AC and DC), ends up being the best choice (and this field is the same used by DateTimeFormatter.ISO_OFFSET_DATE_TIME, by the way). See this reply from Soen to better understand the details.


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

Just to illustrate:

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, the DateTimeFormatter returned accepted April 31st, setting it for April 30th. Already DateTimeFormatter.ISO_OFFSET_DATE_TIME spear one DateTimeParseException, because the date is invalid.

To use ofPattern and do not accept invalid dates, just use the suggested solution in this answer:

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

Using ResolverStyle.STRICT, the DateTimeFormatter will only accept valid dates.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.