En Java, el Locale define cosas que están relacionadas con cómo la gente quiere ver las cosas (como formatos de moneda, el nombre de los meses y cuándo comienza una semana).
Al analizar el nombre de un mes (con un DateTimeFormatter ) comienza a ser complicado.
Si usa Locale.US o Locale.ENGLISH , septiembre tiene la forma abreviada Sep .
Si usa Locale.UK , septiembre también tiene la forma abreviada Sep en Java 11 ... pero cuando prueba Java 17, tiene Sept (debido a los cambios en el final de Unicode CLDR por lo que pregunté si esto era correcto ).
El efecto es que mis pruebas comenzaron a fallar al intentar compilar con Java 17.
La razón por la que mi código actual usa Locale.UK en lugar de Locale.ENGLISH es porque en Java Locale.ENGLISH en realidad no es solo inglés sino también la forma estadounidense no ISO de definir una semana (usan el domingo como el primer día de la semana) . Quiero tenerlo de la manera ISO.
Simplemente:
WeekFields.ISO = WeekFields.of(Locale.UK) = WeekFields[MONDAY,4]WeekFields.of(Locale.ENGLISH) = WeekFields.of(Locale.US) = WeekFields[SUNDAY,1]Entonces, comenzando con Java 17, aún no he podido encontrar una configuración regional integrada que funcione correctamente.
En mi mente, tengo que tomar Locale.ENGLISH y cambiar WeekFields o tomar Locale.UK y cambiar el nombre corto del mes de septiembre a lo que necesito.
Mi pregunta es ¿cómo hago esto (en Java 17)?
¿O hay una mejor manera de arreglar esto?
Actualización 1:
Así que parece que necesitaré no solo un analizador que acepte "Sep", sino uno que acepte una combinación de "Sept" y "Sep" para inglés.
Actualización 2:
Encontré una manera de manejar esto usando SPI.
Lo estoy documentando aquí como una posibilidad que puede funcionar para otros (no funciona para mi contexto).
Como experimento creé una clase:
package nl.basjes.parse.httpdlog.dissectors.locale; import java.util.Locale; import java.util.spi.CalendarDataProvider; import static java.util.Calendar.MONDAY; public class CalendarDataProviderISO8601 extends CalendarDataProvider { public static final Locale ENGLISH_ISO = new Locale("en", "", "ISO"); @Override public int getFirstDayOfWeek(Locale locale) { return MONDAY; } @Override public int getMinimalDaysInFirstWeek(Locale locale) { return 4; } @Override public Locale[] getAvailableLocales() { return new Locale[]{ENGLISH_ISO}; } } y un archivo ./src/main/resources/META-INF/services/java.util.spi.CalendarDataProvider con
nl.basjes.parse.httpdlog.dissectors.locale.CalendarDataProviderISO8601Debido a que esta es solo una variante del "inglés" sin región, tomará todo desde "inglés" y pondrá la clase anterior sobre él.
Aunque esto funciona, no puedo usarlo.
El problema es que aunque http://openjdk.java.net/jeps/252 describe The default lookup order will be CLDR, COMPAT, SPI, la realidad actual es que el SPI se eliminó de esta lista en este cambio debido a la deprecating the Extension Mechanism .
Entonces, para usar esta construcción, la clase debe estar en el classpath al inicio y la opción de línea de comando -Djava.locale.providers=CLDR,COMPAT,SPI debe pasarse a la JVM.
Dado que mi biblioteca ( https://github.com/nielsbasjes/logparser/ ) también se usa en situaciones (como Apache Flink/Beam/Drill/Pig) donde las clases se envían de una manera más dinámica (serializadas y transportadas a un ya ejecutando JVM) a varias máquinas, esta construcción no se puede utilizar.
Actualmente no conozco una forma dynamic de hacer algo como esto en Java.