nueva localdatetime improvements fechas example ejemplo conociendo java date java-8 java-time

java - improvements - localdatetime to date



La letra de patrón de mes DateTimeFormatter "L" falla (3)

Nombre del mes "independiente"

Creo que ''L'' está destinado a idiomas que usan una palabra diferente para el mes en comparación con la forma en que se usa en una fecha. Por ejemplo:

Locale russian = Locale.forLanguageTag("ru"); asList("MMMM", "LLLL").forEach(ptrn -> System.out.println(ptrn + ": " + ofPattern(ptrn, russian).format(Month.MARCH)) );

Salida:

MMMM: марта LLLL: Март

No debería haber ninguna razón para usar ''L'' en lugar de ''M'' al analizar una fecha.

Intenté lo siguiente para ver qué configuraciones regionales admiten el formato de nombre de mes independiente:

Arrays.stream(Locale.getAvailableLocales()) .collect(partitioningBy( loc -> "3".equals(Month.MARCH.getDisplayName(FULL_STANDALONE, loc)), mapping(Locale::getDisplayLanguage, toCollection(TreeSet::new)) )).entrySet().forEach(System.out::println);

Los siguientes idiomas obtienen un nombre de mes independiente específico de la localidad de ''LLLL'':

Catalán, chino, croata, checo, finlandés, griego, húngaro, italiano, lituano, noruego, polaco, rumano, ruso, eslovaco, turco, ucraniano

Todos los demás idiomas obtienen "3" como nombre independiente para marzo.

Noté que java.time.format.DateTimeFormatter no puede analizarse como se esperaba. Vea abajo:

import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class Play { public static void tryParse(String d,String f) { try { LocalDate.parse(d, DateTimeFormatter.ofPattern(f)); System.out.println("Pass"); } catch (Exception x) {System.out.println("Fail");} } public static void main(String[] args) { tryParse("26-may-2015","dd-L-yyyy"); tryParse("26-May-2015","dd-L-yyyy"); tryParse("26-may-2015","dd-LLL-yyyy"); tryParse("26-May-2015","dd-LLL-yyyy"); tryParse("26-may-2015","dd-M-yyyy"); tryParse("26-May-2015","dd-M-yyyy"); tryParse("26-may-2015","dd-MMM-yyyy"); tryParse("26-May-2015","dd-MMM-yyyy"); } }

Solo el último intento con tryParse("26-May-2015","dd-MMM-yyyy"); pasará". Según la documentación, LLL debería poder analizar el formato de texto. También tenga en cuenta la sutil diferencia de la ''M'' mayúscula frente a la ''m'' minúscula.

Esto es realmente molesto, ya que por defecto no puedo analizar cadenas formateadas por defecto por Oracle DB

SELECT TO_DATE(SYSDATE,''DD-MON-YYYY'') AS dt FROM DUAL;

Del mismo modo, para el siguiente programa:

import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class Play { public static void output(String f) { LocalDate d = LocalDate.now(); Locale l = Locale.US; // Locale l = Locale.forLanguageTag("ru"); System.out.println(d.format(DateTimeFormatter.ofPattern(f,l))); } public static void main(String[] args) { output("dd-L-yyyy"); output("dd-LLL-yyyy"); output("dd-M-yyyy"); output("dd-MMM-yyyy"); } }

Me sale por debajo de la salida:

28-5-2015 28-5-2015 28-5-2015 28-May-2015

Claramente, el especificador de formato L no trata nada textual, me parece numérico ...

Sin embargo, si cambio la Locale.forLanguageTag("ru") regional a Locale.forLanguageTag("ru") , obtengo el siguiente resultado:

28-5-2015 28-Май-2015 28-5-2015 28-мая-2015

Todo realmente interesante, ¿no te parece?

Las preguntas que tengo son:

  • ¿Es razonable para mí esperar que cada uno de ellos funcione?
  • ¿Deberíamos al menos presentar algunos de estos como un error?
  • ¿No entiendo mal el uso del especificador de patrón L

Citando una parte de la documentación que percibí como ''importa'':

Texto: el estilo de texto se determina en función del número de letras de patrón utilizadas. Menos de 4 letras de patrón usarán la forma corta. Exactamente 4 letras de patrón usarán la forma completa. Exactamente 5 letras de patrón usarán la forma estrecha. Las letras de patrón ''L'', ''c'' y ''q'' especifican la forma independiente de los estilos de texto .

Número: si el recuento de letras es uno, el valor se genera utilizando el número mínimo de dígitos y sin relleno. De lo contrario, el recuento de dígitos se usa como el ancho del campo de salida, con el valor rellenado con cero según sea necesario. Las siguientes letras de patrón tienen restricciones en el recuento de letras. Solo se puede especificar una letra de ''c'' y ''F''. Se pueden especificar hasta dos letras de ''d'', ''H'', ''h'', ''K'', ''k'', ''m'' y ''s''. Se pueden especificar hasta tres letras de ''D''.

Número / texto: si el recuento de letras de patrón es 3 o mayor, use las reglas de texto anteriores . De lo contrario, use las reglas numéricas anteriores.

ACTUALIZAR

He realizado dos presentaciones a Oracle:

  • Solicitud de corrección de errores para el problema LLL (texto de formato largo): JDK-8114833 (ID original de revisión de Oracle: JI-9021661)
  • Solicitud de mejora para el problema de análisis de mes en minúsculas: ID de revisión: 0 (¿eso también es un error?)

Según los javadocs:

Las letras de patrón ''L'', ''c'' y ''q'' especifican la forma independiente de los estilos de texto.

Sin embargo, no pude encontrar mucho sobre lo que se supone que es la forma "independiente". Al mirar el código, veo que usando ''L'' selecciona TextStyle.SHORT_STANDALONE y de acuerdo con ese javadoc:

Texto corto para uso independiente, generalmente una abreviatura. Por ejemplo, el lunes del día de la semana puede mostrar "Mon".

Sin embargo, no es así como parece funcionar. Incluso con tres letras obtengo salida numérica de este código:

DateTimeFormatter pattern = DateTimeFormatter.ofPattern ("dd-LLL-yyyy"); System.out.println (pattern.format (LocalDate.now ()));

Editar

Después de una investigación adicional, parece (por lo que puedo decir) que las versiones "independientes" de estos códigos son para cuando desea cargar sus propios datos independientes de la configuración regional, presumiblemente usando DateTimeFormatterBuilder . Como tal, por defecto DateTimeFormatter no tiene entradas cargadas para TextStyle.SHORT_STANDALONE .


Si bien las otras respuestas brindan información excelente sobre la letra de patrón L y el análisis de fechas, me gustaría agregar que realmente debería evitar el problema por completo. No obtenga la fecha (y la hora) como cadena de su base de datos. En su lugar, use un objeto apropiado de fecha y hora.

String sql = "select sysdate as dt from dual;" PreparedStatement stmt = yourDatabaseConnection.prepareStatement(sql); ResultSet rs = stmt.executeQuery(); if (rs.next()) { LocalDateTime dateTime = rs.getObject("dt", LocalDateTime.class); // do something with dateTime }

(No probado ya que no tengo una base de datos Oracle a mano. Perdone cualquier error tipográfico).