variable tiempo manejo localdatetime java8 horas fecha ejemplo datetimeformatter actual java datetime java-8 java-time

tiempo - manejo de horas en java



Formatee una fecha usando la nueva API de fecha y hora (3)

Me gustaría agregar los siguientes detalles a la respuesta correcta de @James_D:

Antecedentes: la mayoría de las bibliotecas de fecha y hora ( java.util.Calendar en Java, consulte también .Net-DateTime o Date en JavaScript o DateTime en Perl) se basan en el concepto de un tipo temporal universal único para todo uso (en En alemán está la expresión poética "eierlegende Wollmilchsau"). En este diseño no puede haber un campo no admitido. Pero el precio es alto: muchos problemas de tiempo no se pueden manejar adecuadamente con un enfoque tan poco flexible porque es difícil encontrar un denominador común para todo tipo de objetos temporales.

JSR-310 ha elegido otra forma , es decir, permitir diferentes tipos temporales que consisten en conjuntos específicos de tipo de campos incorporados admitidos. La consecuencia natural es que no todos los campos posibles son compatibles con todos los tipos (y los usuarios incluso pueden definir sus propios campos especializados). También es posible solicitar programáticamente cada objeto de tipo TemporalAccessor para su conjunto específico de campos compatibles. Para LocalDate encontramos:

•DAY_OF_WEEK •ALIGNED_DAY_OF_WEEK_IN_MONTH •ALIGNED_DAY_OF_WEEK_IN_YEAR •DAY_OF_MONTH •DAY_OF_YEAR •EPOCH_DAY •ALIGNED_WEEK_OF_MONTH •ALIGNED_WEEK_OF_YEAR •MONTH_OF_YEAR •PROLEPTIC_MONTH •YEAR_OF_ERA •YEAR •ERA

No hay campo HOUR_OF_DAY que explique el problema de UnsupportedTemporalTypeException . Y si miramos el mapeo JSR-310- de los símbolos de patrón a los campos , vemos que el símbolo H está mapeado a HOUR_OF_DAY no soportado:

/** Map of letters to fields. */ private static final Map<Character, TemporalField> FIELD_MAP = new HashMap<>(); static { FIELD_MAP.put(''G'', ChronoField.ERA); FIELD_MAP.put(''y'', ChronoField.YEAR_OF_ERA); FIELD_MAP.put(''u'', ChronoField.YEAR); FIELD_MAP.put(''Q'', IsoFields.QUARTER_OF_YEAR); FIELD_MAP.put(''q'', IsoFields.QUARTER_OF_YEAR); FIELD_MAP.put(''M'', ChronoField.MONTH_OF_YEAR); FIELD_MAP.put(''L'', ChronoField.MONTH_OF_YEAR); FIELD_MAP.put(''D'', ChronoField.DAY_OF_YEAR); FIELD_MAP.put(''d'', ChronoField.DAY_OF_MONTH); FIELD_MAP.put(''F'', ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH); FIELD_MAP.put(''E'', ChronoField.DAY_OF_WEEK); FIELD_MAP.put(''c'', ChronoField.DAY_OF_WEEK); FIELD_MAP.put(''e'', ChronoField.DAY_OF_WEEK); FIELD_MAP.put(''a'', ChronoField.AMPM_OF_DAY); FIELD_MAP.put(''H'', ChronoField.HOUR_OF_DAY); FIELD_MAP.put(''k'', ChronoField.CLOCK_HOUR_OF_DAY); FIELD_MAP.put(''K'', ChronoField.HOUR_OF_AMPM); FIELD_MAP.put(''h'', ChronoField.CLOCK_HOUR_OF_AMPM); FIELD_MAP.put(''m'', ChronoField.MINUTE_OF_HOUR); FIELD_MAP.put(''s'', ChronoField.SECOND_OF_MINUTE); FIELD_MAP.put(''S'', ChronoField.NANO_OF_SECOND); FIELD_MAP.put(''A'', ChronoField.MILLI_OF_DAY); FIELD_MAP.put(''n'', ChronoField.NANO_OF_SECOND); FIELD_MAP.put(''N'', ChronoField.NANO_OF_DAY); }

Este mapeo de campo no significa que el campo sea compatible con el tipo concreto. El análisis se realiza en varios pasos. El mapeo de campo es solo el primer paso. El segundo paso es luego analizar un objeto sin formato de tipo TemporalAccessor . Y, finalmente, analizar delegados al tipo de destino (aquí: LocalDate ) y dejar que decida si acepta todos los valores de campo en el objeto intermedio analizado.

Estaba jugando con la nueva API de fecha y hora, pero al ejecutar esto:

public class Test { public static void main(String[] args){ String dateFormatted = LocalDate.now() .format(DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm:ss")); System.out.println(dateFormatted); } }

Lanza:

Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay at java.time.LocalDate.get0(LocalDate.java:680) at java.time.LocalDate.getLong(LocalDate.java:659) at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298) at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2543) at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182) at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1745) at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1719) at java.time.LocalDate.format(LocalDate.java:1685) at Test.main(Test.java:23)

Cuando miro el código fuente de la clase LocalDate, veo:

private int get0(TemporalField field) { switch ((ChronoField) field) { case DAY_OF_WEEK: return getDayOfWeek().getValue(); case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1; case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1; case DAY_OF_MONTH: return day; case DAY_OF_YEAR: return getDayOfYear(); case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field ''EpochDay'' for get() method, use getLong() instead"); case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1; case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1; case MONTH_OF_YEAR: return month; case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field ''ProlepticMonth'' for get() method, use getLong() instead"); case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year); case YEAR: return year; case ERA: return (year >= 1 ? 1 : 0); } throw new UnsupportedTemporalTypeException("Unsupported field: " + field); }

Como se describe en el documento:

Este método creará un formateador basado en un patrón simple de letras y símbolos como se describe en la documentación de la clase.

Y todas estas letras están defined .

Entonces, ¿por qué DateTimeFormatter.ofPattern no nos permite usar algunas letras de patrones?


LocalDate no tiene la información de hora, por lo que obtiene un UnsupportedTemporalTypeException: Unsupported field: HourOfDay .

Puede utilizar LocalDateTime pero no tiene la información de Zona horaria, por lo que si intenta acceder a ella (incluso utilizando uno de los formateadores predefinidos) obtendrá un UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds .

La clase correcta para mí fue ZonedDateTime que incluye tanto el tiempo como la zona horaria.


LocalDate representa solo una fecha, no un DateTime. Por lo tanto, "HH: mm: ss" no tiene sentido al formatear un LocalDate . Use un LocalDateTime en LocalDateTime lugar, suponiendo que quiera representar tanto una fecha como una hora.