SimpleDateFormat und auf dem Gebietsschema basierende Formatzeichenfolge

82

Ich versuche, ein Datum in Java basierend auf dem angegebenen Gebietsschema auf unterschiedliche Weise zu formatieren. Zum Beispiel möchte ich, dass englische Benutzer "1. November 2009" (formatiert mit "MMM d, yyyy") und norwegische Benutzer "1. November 2009" ("d. MMM. JJJJ") sehen.

Der Monatsteil funktioniert einwandfrei, wenn ich das Gebietsschema zum SimpleDateFormat-Konstruktor hinzufüge, aber was ist mit dem Rest?

Ich hatte gehofft, SimpleDateFormat Formatzeichenfolgen mit Gebietsschemas hinzufügen zu können, aber ich kann keine Möglichkeit finden, dies zu tun. Ist es möglich oder muss ich meinen Code das Gebietsschema überprüfen lassen und die entsprechende Formatzeichenfolge hinzufügen?

fiskeben
quelle
1
Zu Ihrer Information, die störenden alten Datum Zeitklassen wie java.util.Date, java.util.Calendarund java.text.SimpleDateFormatsind jetzt Erbe , durch die verdrängte java.time Klassen in Java gebaut 8 & Java 9. Siehe Tutorial von Oracle .
Basil Bourque

Antworten:

87

Verwenden Sie DateFormat.getDateInstance (int style, Locale locale), anstatt Ihre eigenen Muster mit zu erstellen SimpleDateFormat.

jarnbjo
quelle
1
Danke, das funktioniert OK. Ich habe mich für DateFormat.LONG entschieden, das meinen Bedürfnissen am besten entspricht. Übrigens, norwegisches Gebietsschema und DateFormat.MEDIUM ist Mist (!)
fiskeben
Sie haben Recht, das seltsame MITTLERE Muster für Norwegisch ist mir nie in den Sinn gekommen. Der Wochentag fehlt im Gegensatz zu den meisten anderen Gebietsschemas auch im Format FULL.
jarnbjo
2
Zu Ihrer Information , die problematischen Klassen von java.util.Dateund SimpleDateFormatsind jetzt Legacy, ersetzt durch die java.time-Klassen.
Basil Bourque
87

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

Verwenden Sie den Stil + Gebietsschema : DateFormat.getDateInstance (int style, Gebietsschema Gebietsschema)

Überprüfen Sie http://java.sun.com/j2se/1.5.0/docs/api/java/text/DateFormat.html

Führen Sie das folgende Beispiel aus, um die Unterschiede festzustellen:

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

Ausgabe:

United Kingdom: 25-Sep-2017
USA: Sep 25, 2017
France: 25 sept. 2017
Italy: 25-set-2017
Japan: 2017/09/25
JuanZe
quelle
1
Vergessen Sie nicht die DateFormat.LONGund DateFormat.DEFAULTStile!
JDJ
6
Das Hinzufügen der Ausgabe Ihres Codes wäre vollständiger gewesen
sam
1
Richtige Idee, um Stil und Gebietsschema anzugeben. Aber die verwendeten Klassen sind jetzt veraltet. Die lästigen alten Datum Zeitklassen wie java.util.Date, java.util.Calendarund java.text.SimpleDateFormatsind jetzt Erbe , durch die verdrängte java.time Klassen in Java gebaut 8 & Java 9. Siehe Tutorial von Oracle .
Basil Bourque
15

tl; dr

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

Die lästigen Klassen von java.util.Dateund SimpleDateFormatsind jetzt Legacy, ersetzt durch die java.time-Klassen.

LocalDate

Die LocalDateKlasse repräsentiert einen Nur-Datum-Wert ohne Tageszeit und ohne Zeitzone.

Eine Zeitzone ist entscheidend für die Bestimmung eines Datums. Für jeden Moment variiert das Datum weltweit je nach Zone. Zum Beispiel ist ein paar Minuten nach Mitternacht in Paris Frankreich ein neuer Tag, während es in Montréal Québec noch „gestern“ ist .

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

DateTimeFormatter

Verwenden Sie DateTimeFormatterdiese Option , um Zeichenfolgen zu generieren, die nur den Datums- oder Zeitabschnitt darstellen.

Die DateTimeFormatterKlasse kann automatisch lokalisieren .

Geben Sie zum Lokalisieren Folgendes an:

  • FormatStyle um zu bestimmen, wie lang oder abgekürzt die Zeichenfolge sein soll.
  • Locale (a) die menschliche Sprache für die Übersetzung des Namens des Tages, des Monats und dergleichen zu bestimmen und (b) die kulturellen Normen, die Fragen der Abkürzung, Großschreibung, Zeichensetzung und dergleichen entscheiden.

Beispiel:

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

Wenn Sie in die andere Richtung gehen, können Sie eine lokalisierte Zeichenfolge analysieren.

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

Beachten Sie, dass das Gebietsschema und die Zeitzone vollständig orthogonale Probleme sind. Sie können einen Montréal-Moment in japanischer Sprache oder einen Auckland New Zealand-Moment in Hindi-Sprache präsentieren lassen.

Ein weiteres Beispiel: Ändern Sie 6 junio 2012(Spanisch) in 2012-06-06(Standardformat ISO 8601 ). Die java.time-Klassen verwenden standardmäßig ISO 8601-Formate zum Parsen / Generieren von Zeichenfolgen.

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. 

Formate durchlesen

Hier ist ein Beispielcode zum Durchsuchen der Ergebnisse mehrerer Formate in mehreren Gebietsschemas, die automatisch lokalisiert werden.

An EnumSetist eine Implementierung von Set, die sowohl für eine geringe Speichernutzung als auch für eine schnelle Ausführungsgeschwindigkeit beim Sammeln von EnumObjekten hochoptimiert ist . So EnumSet.allOf( FormatStyle.class )gibt uns eine Sammlung von allen vier der FormatStyleENUM - Objekte in einer Schleife. Weitere Informationen finden Sie im Oracle-Lernprogramm zu Aufzählungstypen .

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

Ausgabe.

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

Über java.time

Das java.time- Framework ist in Java 8 und höher integriert. Diese Klassen verdrängen die lästigen alten Legacy - Datum-Zeit - Klassen wie java.util.Date, Calendar, & SimpleDateFormat.

Das Joda-Time- Projekt, das sich jetzt im Wartungsmodus befindet , empfiehlt die Migration zu den Klassen java.time .

Weitere Informationen finden Sie im Oracle-Lernprogramm . Suchen Sie im Stapelüberlauf nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .

Sie können java.time- Objekte direkt mit Ihrer Datenbank austauschen . Verwenden Sie einen JDBC-Treiber, der mit JDBC 4.2 oder höher kompatibel ist . Keine Notwendigkeit für Zeichenfolgen, keine Notwendigkeit für java.sql.*Klassen.

Woher bekomme ich die java.time-Klassen?

Das ThreeTen-Extra- Projekt erweitert java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen von java.time. Sie können einige nützliche Klassen hier wie finden Interval, YearWeek, YearQuarter, und mehr .

Basil Bourque
quelle
8

Lokalisierung der Datumszeichenfolge:

Basierend auf Redsonics Beitrag:

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

wird wie 05- 九月 -2013 sein

Yaro
quelle
3

Dadurch wird das Datum entsprechend dem aktuellen Gebietsschema des Benutzers angezeigt :

So geben Sie Datum und Uhrzeit zurück:

import java.text.DateFormat;    
import java.util.Date;

Date date = new Date();
DateFormat df = DateFormat.getDateTimeInstance();
String myDate = df.format(date);

31. Dezember 1969, 19:00:02 Uhr

Um nur das Datum zurückzugeben, verwenden Sie:

DateFormat.getDateInstance() 

31. Dezember 1969

Live-Liebe
quelle
1

Java 8 Style für ein bestimmtes Datum

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)));
Mircea Stanciu
quelle
Ich glaube, ich habe diese Art von Lösung vor einem Jahr behandelt.
Basil Bourque
0
String text = new SimpleDateFormat("E, MMM d, yyyy").format(date);
Hadid Graphics
quelle
0

Hoffe das hilft jemandem. Im folgenden Code finden Sie den Code, der die Gebietsschemainstanz akzeptiert und das länderspezifische Datumsformat / -muster zurückgibt.

public static String getLocaleDatePattern(Locale locale) {
    // Validating if Locale instance is null
    if (locale == null || locale.getLanguage() == null) {
        return "MM/dd/yyyy";
    }
    // Fetching the locale specific date pattern
    String localeDatePattern = ((SimpleDateFormat) DateFormat.getDateInstance(
            DateFormat.SHORT, locale)).toPattern();
    // Validating if locale type is having language code for Chinese and country
    // code for (Hong Kong) with Date Format as - yy'?'M'?'d'?'
    if (locale.toString().equalsIgnoreCase("zh_hk")) {
        // Expected application Date Format for Chinese (Hong Kong) locale type
        return "yyyy'MM'dd";
    }
    // Replacing all d|m|y OR Gy with dd|MM|yyyy as per the locale date pattern
    localeDatePattern = localeDatePattern.replaceAll("d{1,2}", "dd")
            .replaceAll("M{1,2}", "MM")
            .replaceAll("y{1,4}|Gy", "yyyy");
    // Replacing all blank spaces in the locale date pattern
    localeDatePattern = localeDatePattern.replace(" ", "");
    // Validating the date pattern length to remove any extract characters
    if (localeDatePattern.length() > 10) {
        // Keeping the standard length as expected by the application
        localeDatePattern = localeDatePattern.substring(0, 10);
    }
    return localeDatePattern;
}
Dinesh Lomte
quelle
-2

Java8

 import java.time.format.DateTimeFormatter;         
 myDate.format(DateTimeFormatter.ofPattern("dd-MMM-YYYY",new Locale("ar")))
Abdennour TOUMI
quelle
Wenn Sie ofPatternein Gebietsschema-Argument verwenden, erhalten Sie den Monatsnamen in der gewünschten Sprache, jedoch nicht in den in der Frage angeforderten Formaten. Die Verwendung von Großbuchstaben YYYYführt in Eckfällen zu falschen und sehr überraschenden Ergebnissen. Die Verwendung von Java 8 ist eine gute Idee.
Ole VV