SimpleDateFormat y cadena de formato basada en la configuración regional

Estoy tratando de formatear una fecha en Java de diferentes maneras en función de la configuración regional dada. Por ejemplo, quiero que los usuarios de inglés vean “1 de noviembre de 2009” (formateado por “MMM d, yyyy”) y que los usuarios noruegos vean “1. nov. 2009” (“d. MMM. Aaaa”).

La parte del mes funciona bien si agrego la configuración regional al constructor SimpleDateFormat, pero ¿qué pasa con el rest?

Esperaba poder agregar cadenas de formato emparejadas con configuraciones regionales a SimpleDateFormat, pero no puedo encontrar ninguna forma de hacerlo. ¿Es posible o debo permitir que mi código verifique la configuración regional y agregue la cadena de formato correspondiente?

Use DateFormat.getDateInstance (int style, configuración regional) en lugar de crear sus propios patrones con SimpleDateFormat .

 SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE dd MMM yyyy", Locale.ENGLISH); String formatted = dateFormat.format(the_date_you_want_here); 

Use el estilo + configuración regional : DateFormat.getDateInstance (estilo int, configuración regional de configuración regional)

Compruebe http://java.sun.com/j2se/1.5.0/docs/api/java/text/DateFormat.html

Ejecute el siguiente ejemplo para ver las diferencias:

 import java.text.DateFormat; import java.util.Date; import java.util.Locale; public class DateFormatDemoSO { public static void main(String args[]) { int style = DateFormat.MEDIUM; //Also try with style = DateFormat.FULL and DateFormat.SHORT Date date = new Date(); DateFormat df; df = DateFormat.getDateInstance(style, Locale.UK); System.out.println("United Kingdom: " + df.format(date)); df = DateFormat.getDateInstance(style, Locale.US); System.out.println("USA: " + df.format(date)); df = DateFormat.getDateInstance(style, Locale.FRANCE); System.out.println("France: " + df.format(date)); df = DateFormat.getDateInstance(style, Locale.ITALY); System.out.println("Italy: " + df.format(date)); df = DateFormat.getDateInstance(style, Locale.JAPAN); System.out.println("Japan: " + df.format(date)); } } 

Salida:

 United Kingdom: 25-Sep-2017 USA: Sep 25, 2017 France: 25 sept. 2017 Italy: 25-set-2017 Japan: 2017/09/25 

tl; dr

 LocalDate.now().format( DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ) .withLocale( new Locale( "no" , "NO" ) ) ) 

Las clases problemáticas de java.util.Date y SimpleDateFormat ahora son heredadas, suplantadas por las clases java.time.

LocalDate

La clase LocalDate representa un valor de solo fecha sin hora del día y sin zona horaria.

Un huso horario es crucial para determinar una fecha. Para cualquier momento dado, la fecha varía alrededor del mundo por zona. Por ejemplo, unos minutos después de la medianoche en París, Francia es un nuevo día cuando todavía está “ayer” en Montreal Québec .

 ZoneId z = ZoneId.of( "America/Montreal" ); LocalDate today = LocalDate.now( z ); 

DateTimeFormatter

Use DateTimeFormatter para generar cadenas que representen solo la porción de fecha o la porción de tiempo.

La clase DateTimeFormatter puede localizarse automáticamente.

Para localizar, especifique:

  • FormatStyle para determinar cuánto tiempo o abreviar debe ser la cadena.
  • Locale para determinar (a) el idioma humano para la traducción del nombre del día, nombre del mes y demás, y (b) las normas culturales que deciden los problemas de abreviación, uso de mayúsculas, puntuación, etc.

Ejemplo:

 Locale l = Locale.CANADA_FRENCH ; DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.FULL ).withLocale( l ); String output = ld.format( f ); 

Yendo en la otra dirección, puede analizar una cadena localizada.

 LocalDate ld = LocalDate.parse( input , f ); 

Tenga en cuenta que la configuración regional y la zona horaria son cuestiones completamente ortogonales. Puede presentar un momento de Montreal en japonés o un momento de Auckland Nueva Zelanda presentado en idioma hindi.

Otro ejemplo: Cambie 6 junio 2012 (español) a 2012-06-06 (formato estándar ISO 8601 ). Las clases java.time usan formatos ISO 8601 por defecto para analizar / generar cadenas.

 String input = "6 junio 2012"; Locale l = new Locale ( "es" , "ES" ); DateTimeFormatter f = DateTimeFormatter.ofPattern ( "d MMMM uuuu" , l ); LocalDate ld = LocalDate.parse ( input , f ); String output = ld.toString(); // 2012-06-06. 

Examinar formatos

Aquí hay un código de ejemplo para examinar los resultados de múltiples formatos en múltiples configuraciones regionales, localizadas automáticamente.

Un EnumSet es una implementación de Set , altamente optimizada tanto para el uso de poca memoria como para la velocidad de ejecución rápida al recolectar objetos Enum . Por lo tanto, EnumSet.allOf( FormatStyle.class ) nos da una colección de los cuatro objetos enum de FormatStyle en bucle. Para obtener más información, consulte Oracle Tutorial sobre tipos de enumeración .

 LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ); List < Locale > locales = new ArrayList <>( 3 ); locales.add( Locale.CANADA_FRENCH ); locales.add( new Locale( "no" , "NO" ) ); locales.add( Locale.US ); // Or use all locales (almost 800 of them, for about 120K text results). // Locale[] locales = Locale.getAvailableLocales(); // All known locales. Almost 800 of them. for ( Locale locale : locales ) { System.out.println( "------| LOCALE: " + locale + " — " + locale.getDisplayName() + " |----------------------------------" + System.lineSeparator() ); for ( FormatStyle style : EnumSet.allOf( FormatStyle.class ) ) { DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( style ).withLocale( locale ); String output = ld.format( f ); System.out.println( output ); } System.out.println( "" ); } System.out.println( "« fin »" + System.lineSeparator() ); 

Salida.

 ------| LOCALE: fr_CA — French (Canada) |---------------------------------- mardi 23 janvier 2018 23 janvier 2018 23 janv. 2018 18-01-23 ------| LOCALE: no_NO — Norwegian (Norway) |---------------------------------- tirsdag 23. januar 2018 23. januar 2018 23. jan. 2018 23.01.2018 ------| LOCALE: en_US — English (United States) |---------------------------------- Tuesday, January 23, 2018 January 23, 2018 Jan 23, 2018 1/23/18 « fin » 

Acerca de java.time

El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las problemáticas antiguas clases heredadas de fecha y hora como java.util.Date , Calendar y SimpleDateFormat .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

Puede intercambiar objetos java.time directamente con su base de datos. Use un controlador JDBC que cumpla con JDBC 4.2 o posterior. Sin necesidad de cadenas, sin necesidad de clases java.sql.* .

¿Dónde obtener las clases de java.time?

  • Java SE 8 , Java SE 9 y posterior
    • Incorporado.
    • Parte de la API Java estándar con una implementación integrada.
    • Java 9 agrega algunas características y correcciones menores.
  • Java SE 6 y Java SE 7
    • Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 en ThreeTen-Backport .
  • Androide
    • Versiones posteriores de las implementaciones del paquete de Android de las clases java.time.
    • Para Android anterior, el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Consulte Cómo utilizar ThreeTenABP ….

El proyecto ThreeTen-Extra amplía java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval , YearWeek , YearQuarter y más .

Localización de cadena de fecha:

Basado en la publicación de redsonic:

 private String localizeDate(String inputdate, Locale locale) { Date date = new Date(); SimpleDateFormat dateFormatCN = new SimpleDateFormat("dd-MMM-yyyy", locale); SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy"); try { date = dateFormat.parse(inputdate); } catch (ParseException e) { log.warn("Input date was not correct. Can not localize it."); return inputdate; } return dateFormatCN.format(date); } String localizedDate = localizeDate("05-Sep-2013", new Locale("zh","CN")); 

será como 05- 九月 -2013

Esto mostrará la fecha de acuerdo con la configuración regional actual del usuario:

 import java.text.DateFormat; import java.util.Date; Date date = new Date(); DateFormat df = DateFormat.getDateTimeInstance(); String myDate = df.format(date); 

31 de diciembre de 1969 7:00:02 p.m.

 DateFormat.getDateInstance() 

31 de diciembre de 1969

 String text = new SimpleDateFormat("E, MMM d, yyyy").format(date); 

Java 8 Style para una fecha determinada

 LocalDate today = LocalDate.of(1982, Month.AUGUST, 31); System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.ENGLISH))); System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.FRENCH))); System.out.println(today.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.JAPANESE))); 

Java8

  import java.time.format.DateTimeFormatter; myDate.format(DateTimeFormatter.ofPattern("dd-MMM-YYYY",new Locale("ar")))