SimpleDateFormat e cadeia de formato baseada em locale

Eu estou tentando formatar uma data em Java de maneiras diferentes com base na localidade dada. Por exemplo, quero que os usuários ingleses vejam “1 de novembro de 2009” (formatado por “MMM d, yyyy”) e os usuários noruegueses vejam “1. nov. 2009” (“d. MMM. Yyyy”).

A parte do mês funciona bem se eu adicionar a localidade ao construtor SimpleDateFormat, mas e quanto ao resto?

Eu estava esperando poder adicionar cadeias de caracteres de formato emparelhadas com localidades para SimpleDateFormat, mas não consigo encontrar nenhuma maneira de fazer isso. É possível ou preciso deixar meu código verificar a localidade e adicionar a string de formato correspondente?

Use DateFormat.getDateInstance (int style, Locale locale) em vez de criar seus próprios padrões com SimpleDateFormat .

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

Use o estilo + locale : DateFormat.getDateInstance (int style, Locale locale)

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

Execute o seguinte exemplo para ver as diferenças:

 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)); } } 

Saída:

 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" ) ) ) 

As classs problemáticas de java.util.Date e SimpleDateFormat agora são herdadas, suplantadas pelas classs java.time.

LocalDate

A class LocalDate representa um valor somente de datas sem hora do dia e sem fuso horário.

Um fuso horário é crucial para determinar uma data. Para qualquer momento, a data varia ao redor do globo por zona. Por exemplo, poucos minutos depois da meia-noite em Paris, a França é um novo dia ainda em “ontem” em Montreal, Quebec .

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

DateTimeFormatter

Use DateTimeFormatter para gerar cadeias que representam apenas a parte da data ou a parte do tempo.

A class DateTimeFormatter pode localizar automaticamente.

Para localizar, especifique:

  • FormatStyle para determinar quanto tempo ou abreviada deve ser a string.
  • Locale para determinar (a) a linguagem humana para tradução do nome do dia, nome do mês e tal, e (b) as normas culturais que decidem questões de abreviação, letras maiúsculas, pontuação e outras.

Exemplo:

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

Indo na outra direção, você pode analisar uma string localizada.

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

Observe que o local e o fuso horário são problemas completamente ortogonais. Você pode ter um momento de Montreal apresentado em língua japonesa ou um momento de Auckland Nova Zelândia apresentado em idioma hindi.

Outro exemplo: Mude 6 junio 2012 (espanhol) para 2012-06-06 (formato padrão ISO 8601 ). As classs java.time usam os formatos ISO 8601 por padrão para analisar / gerar sequências.

 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. 

Formatos de folhetos

Aqui está um código de exemplo para examinar os resultados de vários formatos em vários locais, localizados automaticamente.

Um EnumSet é uma implementação do Set , altamente otimizada para uso de pouca memory e rápida velocidade de execução ao coletar objects Enum . Então, EnumSet.allOf( FormatStyle.class ) nos dá uma coleção de todos os quatro objects enum FormatStyle para fazer um loop. Para mais informações, consulte o Oracle Tutorial em tipos enum .

 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() ); 

Saída.

 ------| 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 » 

Sobre o java.time

O framework java.time está embutido no Java 8 e posterior. Essas classs substituem as antigas classs herdadas de data e hora legadas , como java.util.Date , Calendar e SimpleDateFormat .

O projeto Joda-Time , agora em modo de manutenção , aconselha a migration para as classs java.time .

Para saber mais, veja o Oracle Tutorial . E pesquise o Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .

Você pode trocar objects java.time diretamente com seu database. Use um driver JDBC compatível com o JDBC 4.2 ou posterior. Não há necessidade de strings, não há necessidade de classs java.sql.* .

Onde obter as classs java.time?

  • Java SE 8 , Java SE 9 e posterior
    • Construídas em.
    • Parte da API Java padrão com uma implementação integrada.
    • O Java 9 adiciona alguns resources e correções menores.
  • Java SE 6 e Java SE 7
    • Grande parte da funcionalidade java.time é transferida para o Java 6 e 7 no ThreeTen-Backport .
  • Android
    • Versões posteriores das implementações do pacote Android das classs java.time.
    • Para o Android anterior, o projeto ThreeTenABP adapta o ThreeTen-Backport (mencionado acima). Veja Como usar o ThreeTenABP… .

O projeto ThreeTen-Extra estende java.time com classs adicionais. Este projeto é um campo de testes para possíveis futuras adições ao java.time. Você pode encontrar algumas classs úteis aqui como Interval , YearWeek , YearQuarter e muito mais .

Localização da string de data:

Baseado no post do 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

Isso exibirá a data de acordo com a localidade atual do usuário:

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

31 de dezembro de 1969 7:00:02

 DateFormat.getDateInstance() 

31 de dezembro de 1969

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

Estilo Java 8 para uma determinada data

 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")))