Jim
Jim

Reputation: 19582

Why is locale ignored for SimpleDateFormat?

According the javadocs I can create a SimpleDateFormat that is locale aware.
But trying out the following code:

Locale [] locales = {
                Locale.GERMANY,  
                Locale.CANADA_FRENCH,  
                Locale.CHINA,  
                Locale.ITALIAN,  
                Locale.JAPANESE,  
                Locale.ENGLISH  
        };    

try {  
            for(Locale locale : locales) {  
                final SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);    
                System.out.println(myFormat.parse("2017-04-01 12:00:01"));  

            }  
        } catch (ParseException e) {  
            e.printStackTrace();  
        }  

I see in the output:

Sat Apr 01 12:00:01 CEST 2017  
Sat Apr 01 12:00:01 CEST 2017  
Sat Apr 01 12:00:01 CEST 2017  
Sat Apr 01 12:00:01 CEST 2017  
Sat Apr 01 12:00:01 CEST 2017  
Sat Apr 01 12:00:01 CEST 2017  

So why are all the same date format regardless of the locale?

Update after comment:

for(Locale locale : locales) {  
                    System.out.println("Locale " + locale);
                    final SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);    
                    System.out.println(myFormat.parse("2017-04-01 12:00:01"));   
                    System.out.println(myFormat.format(myFormat.parse("2017-04-01 12:00:01")));  
                System.out.println("-----------");      

                }  

The above snippet prints:

-----------  
Locale zh_CN  
Sat Apr 01 12:00:01 CEST 2017  
2017-04-01 12:00:01  
-----------  
Locale it  
Sat Apr 01 12:00:01 CEST 2017  
2017-04-01 12:00:01  
-----------  
Locale ja  
Sat Apr 01 12:00:01 CEST 2017  
2017-04-01 12:00:01  
-----------  
Locale en  
Sat Apr 01 12:00:01 CEST 2017  
2017-04-01 12:00:01   

-----------  

Update 2:
The following code takes locale into account:

final SimpleDateFormat myFormat1 = new SimpleDateFormat("dd-MMM-yyyy");  
final SimpleDateFormat myFormat = new SimpleDateFormat("dd-MMM-yyyy", locale);   
Date date = myFormat1.parse("05-Apr-2017");  
String out = myFormat.format(date);  
System.out.println(out);   
System.out.println("-----------");  

Output is:

Locale de_DE  
05-Apr-2017  
-----------  
Locale fr_CA  
05-avr.-2017  
-----------  
Locale zh_CN  
05-四月-2017  
-----------  
Locale it  
05-apr-2017  
-----------  
Locale ja  
05-4-2017  
-----------  
Locale en  
05-Apr-2017  
-----------  

But how come this works as (I) expected? Why does yyyy-MM-dd HH:mm:ss and dd-MMM-yyyy behave so differently?

Upvotes: 2

Views: 3874

Answers (4)

Prajwal Shrestha
Prajwal Shrestha

Reputation: 21

If you are using it as above (by specifying pattern), Locale does not change the order. It does not change MM/dd/yy to dd/MM/yy.

Locale only changes Apr to apr or to avr or to ....

If you wish to change it based on locale, then you'll have to specify the pattern using DateFormat.LONG or FormatStyle.LONG.

Upvotes: 0

john16384
john16384

Reputation: 8064

Since you seem to want to get a standard format for a locale, you should do this:

DateFormat.getDateTimeInstance(DateFormat.LONG, Locale.FRANCE);

Now you don't have to specify a pattern, instead the pattern will be one that is common for the given Locale.

Upvotes: 0

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521914

As this answer discusses, a Locale does not have a proper timezone. Hence, when you parse your date string, the default timezone is being used, which appears to be CEST, i.e. somewhere in the Midwest. If you instead assign timezones to your SimpleDateFormat you will get the behavior you want:

String[] tzs = new String[]{
    "Europe/Berlin",
    "Canada/Eastern",
    "Asia/Shanghai",
    "Europe/Rome",
    "Asia/Tokyo",
    "America/New_York"
};

for (String tz : tzs) {
    SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");
    TimeZone timeZone = TimeZone.getTimeZone(tz);
    myFormat.setTimeZone(timeZone);
    System.out.println(myFormat.format(new Date()));
}

Output:

2017-04-11 09:52:42 CEST
2017-04-11 03:52:42 EDT
2017-04-11 15:52:46 CST
2017-04-11 09:52:47 CEST
2017-04-11 16:52:49 JST
2017-04-11 03:52:50 EDT

If you want to convert a date string into a timestamp as show about, then you can go through a Java Date object. Note that a Java Date does not have a timezone, it is just an arbitrary point in time.

Upvotes: 3

john16384
john16384

Reputation: 8064

It is not ignored, but you are parsing a date from a String, that gets converted to a java.util.Date. These always print in the same way.

If instead you had used the format method, you would get the expected results:

Date date = myFormat.parse("2017-04-01 12:00:01");   // Creates a Date object

String locallyFormattedDate = myFormat.format(date);  // formats that Date object according to locale.

Upvotes: 1

Related Questions