fiskeben
fiskeben

Reputation: 3467

SimpleDateFormat and locale based format string

I'm trying to format a date in Java in different ways based on the given locale. For instance I want English users to see "Nov 1, 2009" (formatted by "MMM d, yyyy") and Norwegian users to see "1. nov. 2009" ("d. MMM. yyyy").

The month part works OK if I add the locale to the SimpleDateFormat constructor, but what about the rest?

I was hoping I could add format strings paired with locales to SimpleDateFormat, but I can't find any way to do this. Is it possible or do I need to let my code check the locale and add the corresponding format string?

Upvotes: 101

Views: 272605

Answers (10)

Dinesh Lomte
Dinesh Lomte

Reputation: 609

Hope this helps someone. Please find in the below code which accepts Locale instance and returns the locale specific date format/pattern.

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

Upvotes: 1

live-love
live-love

Reputation: 52366

This will display the date according to user's current locale:

To return date and time:

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

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

Dec 31, 1969 7:00:02 PM

To return date only, use:

DateFormat.getDateInstance() 

Dec 31, 1969

Upvotes: 5

Basil Bourque
Basil Bourque

Reputation: 338181

tl;dr

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

The troublesome classes of java.util.Date and SimpleDateFormat are now legacy, supplanted by the java.time classes.

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone.

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

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

DateTimeFormatter

Use DateTimeFormatter to generate strings representing only the date-portion or the time-portion.

The DateTimeFormatter class can automatically localize.

To localize, specify:

  • FormatStyle to determine how long or abbreviated should the string be.
  • Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.

Example:

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

Going the other direction, you can parse a localized string.

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

Note that the locale and time zone are completely orthogonal issues. You can have a Montréal moment presented in Japanese language or an Auckland New Zealand moment presented in Hindi language.

Another example: Change 6 junio 2012 (Spanish) to 2012-06-06 (standard ISO 8601 format). The java.time classes use ISO 8601 formats by default for parsing/generating strings.

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. 

Peruse formats

Here is some example code for perusing the results of multiple formats in multiple locales, automatically localized.

An EnumSet is an implementation of Set, highly optimized for both low memory usage and fast execution speed when collecting Enum objects. So, EnumSet.allOf( FormatStyle.class ) gives us a collection of all four of the FormatStyle enum objects to loop. For more info, see Oracle Tutorial on enum types.

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

Output.

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

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 22

Mircea Stanciu
Mircea Stanciu

Reputation: 3753

Java 8 Style for a given date

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

Upvotes: 2

JuanZe
JuanZe

Reputation: 8157

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

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

Run the following example to see the differences:

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

Output:

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

Upvotes: 35

Mohammad Zaer
Mohammad Zaer

Reputation: 696

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

Upvotes: 0

jarnbjo
jarnbjo

Reputation: 34313

Use DateFormat.getDateInstance(int style, Locale locale) instead of creating your own patterns with SimpleDateFormat.

Upvotes: 97

redochka
redochka

Reputation: 12819

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

Upvotes: 96

Abdennour TOUMI
Abdennour TOUMI

Reputation: 93163

Java8

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

Upvotes: -2

Yaro
Yaro

Reputation: 684

Localization of date string:

Based on redsonic's post:

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

will be like 05-九月-2013

Upvotes: 9

Related Questions