He estado tratando de utilizar DateTimeFormatter a las cadenas de fecha / tiempo de análisis de la forma "20141112152340". Cuando llamo formatter.parse (entrada); se genera una excepción:
java.time.format.DateTimeParseException: Texto '20141112152340' no se pudo analizar en el índice 14
Aquí es un reproductor completo mínima:
package com.example.minimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
public class Reproducer {
public static void main(String[] args) {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR) // 4
.appendValue(ChronoField.MONTH_OF_YEAR) // 2
.appendValue(ChronoField.DAY_OF_MONTH) // 2
.appendValue(ChronoField.HOUR_OF_DAY) // 2
.appendValue(ChronoField.MINUTE_OF_HOUR) // 2
.appendValue(ChronoField.SECOND_OF_MINUTE) // 2
.toFormatter()
// Using the default ResolverStyle appears to make no difference.
.withResolverStyle(ResolverStyle.STRICT); // expect 14 characters
String input = "20141112152340";
System.out.printf("length of input is %02d: [%s]; format is %s\n", input.length(), input, formatter.toString());
// When the minute of hour is < 10, it is rendered without zero-padding. Perhaps this
// is related. But, the same problem is reproducible on input strings that do not contain zeroes.
System.out.printf("Current local time in that format is [%s]\n", formatter.format(LocalDateTime.now()));
// The following line throws java.time.format.DateTimeParseException: Text '20140816152340' could not be parsed at index 14
TemporalAccessor parsed = formatter.parse(input);
// NOTREACHED
LocalDateTime stamp = parsed.query(LocalDateTime::from);
System.out.println("Time stamp is " + stamp.toString());
}
}
Aquí está la salida de este programa:
length of input is 14: [20141112152340]; format is Value(Year)Value(MonthOfYear)Value(DayOfMonth)Value(HourOfDay)Value(MinuteOfHour)Value(SecondOfMinute)
Current local time in that format is [20191010183335]
Exception in thread "main" java.time.format.DateTimeParseException: Text '20141112152340' could not be parsed at index 14
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1874)
at com.example.minimal.Reproducer.main(Reproducer.java:28)
Por lo que yo puedo decir, el analizador está rescatando en el punto que llega al final de la cadena. Por offchance que esto sucede porque está en busca de más datos que he intentado cambiar el estilo de resolución del defecto a la estricta, pero esto parece hacer ninguna diferencia.
Mi pregunta es, ¿por qué sucede esto, y cómo puedo corregir mi código para que pueda analizar esta representación de la fecha / hora?
La siguiente formateador funciona para mí:
DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
El toString()
tanto de formateadores revela la diferencia:
Value(Year)Value(MonthOfYear)Value(DayOfMonth)Value(HourOfDay)Value(MinuteOfHour)Value(SecondOfMinute)
vs
Value(YearOfEra,4,19,EXCEEDS_PAD)Value(MonthOfYear,2)Value(DayOfMonth,2)Value(HourOfDay,2)Value(MinuteOfHour,2)Value(SecondOfMinute,2)
Como se puede ver, la segunda formateador, que es la versión de trabajo, parece tener ancho de los campos explícitos, así como explícita SignStyle
Podemos crear el mismo formateador usando el constructor:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR_OF_ERA, 4, 19, SignStyle.EXCEEDS_PAD)
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.appendValue(ChronoField.HOUR_OF_DAY, 2)
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT);
Sin embargo, parece que se puede sustituir YEAR_OF_ERA
con YEAR
un resultado similar.