How to convert the String "20190930120000[-3:BRT]" to Localdatetime

Asked

Viewed 294 times

3

I got the following String: "20190930120000[-3:BRT]".

I need to convert to LocalDateTime.

Does anyone know the mask to be used in DateTimeFormatter.ofPattern("?????")?

I’ve come this far:

LocalDateTime dataDoLancamento;
ZonedDateTime z = ZonedDateTime.parse("20190930120000[-3:BRT]",DateTimeFormatter.ofPattern("yyyyMMddHHmmss") );
dataDoLancamento =  z.toLocalDateTime();

But I end up getting that mistake:

 java.time.format.DateTimeParseException: Text '20190930120000[-3:BRT]' could not be parsed, unparsed text found at index 14

1 answer

4


The excerpt -3:BRT I believe it’s the offset (-3, the difference in hours with respect to UTC) and the Timezone (BRT is the acronym commonly used for "Brasilia Time", which is the Official Time of Brasilia).

That said, in Java 8 it is not possible to do the Parsing of offsets one-digit, as is the case with -3. In this version of JDK, the API only accepts two-digit, as -03 for example. This was only fixed in Java 9.

So the way is to manipulate the String manually.


A first alternative is to simply skip the "-3:BRT" section, since you’re only interested in the date and time (and from what I understand, you don’t want to do conversions between time zones, you just want to take the date and time values that are on String, then just ignore this very stretch):

String s = "20190930120000[-3:BRT]";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuuMMddHHmmss");
LocalDateTime dt = LocalDateTime.parse(s.split("\\[")[0], parser);

But if you want to get one ZonedDateTime, considering the offset and the Timezone that are on String, then it’s a little more complicated.

In Java 8, we have to add the zero in front of 3 so that the offset be with 2 digits, because then it is possible to do the Parsing:

String s = "20190930120000[-3:BRT]";
Set<ZoneId> preferredZones = new HashSet<ZoneId>();
preferredZones.add(ZoneId.of("America/Sao_Paulo"));
DateTimeFormatter parser = new DateTimeFormatterBuilder()
    // data, hora e "["
    .appendPattern("uuuuMMddHHmmss'['")
    // offset e os dois pontos
    .appendOffset("+HH", "+00").appendLiteral(':')
    // abreviação do timezone
    .appendZoneText(TextStyle.SHORT, preferredZones)
    // o "]"
    .appendLiteral(']')
    // criar o formatter
    .toFormatter();
ZonedDateTime zdt = ZonedDateTime.parse(s.replaceFirst("(\\d+\\[[-+])(\\d:[A-Z]+\\])", "$10$2"), parser);
LocalDateTime dt = zdt.toLocalDateTime();

To the replace, I use a regex containing two capture groups (bounded by parentheses). The first group has one or more numbers (\\d+), followed by the character [ (which in regex must be escaped with \), followed by a sign of more or less ([-+]). The second group has the number after the sign (only one digit), followed by two dots and one or more letters, and finally the character ].

In the second argument of replace, i use $1 (all that was captured in group 1), a zero, and all that was captured in group 2 ($2). That is, if the value of the offset has only one digit, zero is added. If you already have two digits, no substitution is done.

One detail is that the abbreviations of timezones (such as "BRT") are in many cases ambiguous, in addition to being nothing standardized ("IST", for example, is used in India, Israel and Ireland, and there is many other cases of ambiguities).

Some Apis even map abbreviations to some default, but in the case of DateTimeFormatter, it is necessary to use a Set of "preferred timezones", which will be used to map the abbreviation unambiguously. In this case, I used America/Sao_Paulo, which corresponds to the Time of Brasilia.

Another detail is that the second parameter of method appendOffset is the String used for when the offset is zero. I used "+00", because it seems to be the "pattern" of the strings you are handling. If it is not, just adapt according to your use cases.

Finally, if you’re using Java >= 9, you don’t need to do the replace, just use "+H" in the method appendOffset, getting appendOffset("+H", "+0").


Note also that in the codes above I used uuuu instead of yyyy next year. This answer explains the reason (in the section "Parse and formatting with String").

Browser other questions tagged

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