Reputation: 3467
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
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
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
Reputation: 338181
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.
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 »
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
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
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
Reputation: 696
String text = new SimpleDateFormat("E, MMM d, yyyy").format(date);
Upvotes: 0
Reputation: 34313
Use DateFormat.getDateInstance(int style, Locale locale) instead of creating your own patterns with SimpleDateFormat
.
Upvotes: 97
Reputation: 12819
SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE dd MMM yyyy", Locale.ENGLISH);
String formatted = dateFormat.format(the_date_you_want_here);
Upvotes: 96
Reputation: 93163
import java.time.format.DateTimeFormatter;
myDate.format(DateTimeFormatter.ofPattern("dd-MMM-YYYY",new Locale("ar")))
Upvotes: -2
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