为什么忽略简单日期格式的区域设置



根据javadocs,我可以创建一个可以识别语言环境的SimpleDateFormat
但是尝试以下代码:

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

我在输出中看到:

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  

那么,为什么无论区域设置如何,日期格式都相同呢?

评论后更新:

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

上面的代码片段打印:

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

更新 2:
以下代码考虑了区域设置:

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

输出为:

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

但是,为什么这像(我(预期的那样工作?为什么 yyyy-MM-dd HH:mm:ssdd-MMM-yyyy的行为如此不同?

正如这个答案所讨论的,Locale没有合适的时区。 因此,当您解析日期字符串时,将使用默认时区,该时区似乎是 CEST ,即在中西部的某个地方。 如果您改为为SimpleDateFormat分配时区,您将获得所需的行为:

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

输出:

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

如果要将日期字符串转换为时间戳,则可以浏览Java Date对象。 请注意,Java Date没有时区,它只是一个任意时间点。

不会被忽略,但您正在解析字符串中的日期,该日期将转换为java.util.Date。 这些始终以相同的方式打印。

相反,如果您使用的是format方法,您将获得预期的结果:

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.

由于您似乎想要获取区域设置的标准格式,因此您应该这样做:

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

现在,您不必指定模式,而是给定区域设置通用的模式。

如果您如上所述使用它(通过指定模式(,则 Locale 不会更改顺序。它不会将 MM/dd/yy 更改为 dd/MM/yy。

区域设置仅将 Apr 更改为 apr 或 avr 或 ....

如果您希望根据区域设置更改它,则必须使用 DateFormat.LONG 或 FormatStyle.LONG 指定模式。

最新更新