2

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?

Jim
  • 18,826
  • 34
  • 135
  • 254
  • They're not "different." All the `Locale` is doing is formatting the language and style in which the date appears. There is no timezone difference here. – Tim Biegeleisen Apr 13 '17 at 07:23

4 Answers4

3

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.

Community
  • 1
  • 1
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • I was expecting to see e.g. for USA locale `04/1/2017 12:00:01` etc i.e. the output to be printed in a way that makes sense for that locale. Maybe I am misunderstanding something? – Jim Apr 11 '17 at 09:17
  • @Jim Then just use the mask `"MM/dd/yyyy HH:mm:ss"` with your `SimpleDateFormat`. I only gave you this example so it would be clearer how the API works. – Tim Biegeleisen Apr 11 '17 at 09:19
  • That's not what I meant. I thought that the api works like this: I pass a text that represents a date and the format the text would be in `yyyy-MM-dd HH:mm:ss zzz` (and that is what I pass actually) and the passing of the locale would be what makes it in the way it is understood for instance in US i.e. would end up with the month first. So it doesn't work like that? – Jim Apr 11 '17 at 12:08
  • Basically I don't understand what is the locale argument in the constructor of `SimpleDateFormat` supposed to do – Jim Apr 11 '17 at 12:27
  • The `Locale` argument in `SimpleDateFormat` is intended for the _language_ used for printing the date. You saw this yourself in the output; the dates were the same, but the labels for those dates matched the locales which you had assigned to the `SimpleDateFormat`. – Tim Biegeleisen Apr 11 '17 at 16:52
  • What do you mean by "the labels for those dates"? Only the example with "05-Apr-2017" has any change based on the locale – Jim Apr 13 '17 at 07:06
  • A `Locale` has no timezone, neither does a `Date`. What isn't clear about this? – Tim Biegeleisen Apr 13 '17 at 07:20
1

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.
john16384
  • 7,800
  • 2
  • 30
  • 44
  • I tested it with `System.out.println(myFormat.format(myFormat.parse("2017-04-01 12:00:01")));` and I get only `2017-04-01 12:00:01` for *all* locales – Jim Apr 11 '17 at 07:46
0

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.

john16384
  • 7,800
  • 2
  • 30
  • 44
  • Please check updated post. I am trying to understand how locale in SimpleDateFormat is used – Jim Apr 11 '17 at 13:33
0

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.