Android SimpleDateFormat在不同的Android版本上提供不同的时区

时间:2018-01-19 19:26:52

标签: android simpledateformat parseexception

我已经阅读了很多关于这个问题的答案,但无法弄清楚为什么会这样。以下是代码。

在类的构造函数中创建日期格式实例变量:

format = new SimpleDateFormat("ddMMyy",Locale.US); 
format.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));

然后,用这种方式:

Date d = format.parse("280218");

致电d.toString()给出:

  • on Lenovo K5 Android 5.1 - > “Wed Feb 28 00:00:00 IST 2018”
  • 在Nexus模拟器Android 7.1上 - > “Wed Feb 28 00:00:00 GMT + 05:30 2018”
  • on Xiaomi Android 4.4 - > “Wed Feb 28 00:00:00 IST 2018”
  • on Xiaomi Redmi Android 4.4 - > “Wed Feb 28 00:00:00 GMT + 05:30 2018”

在后续代码中解析IST日期字符串会得到ParseException,而带有GMT的字符串会被成功解析。

知道为什么会这样吗?

1 个答案:

答案 0 :(得分:0)

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyy", Locale.US);
    LocalDate d = LocalDate.parse("280218", formatter);

    String dToString = d.toString();
    System.out.println(dToString);

    LocalDate parsedBack = LocalDate.parse(dToString);
    System.out.println(parsedBack);

打印(两条相同的行):

2018-02-28
2018-02-28

所有设备的结果都是一样的。

我不确定你为什么要做你正在做的事情,所以我可能没有完全击中你所追求的。我试图仅使用java.time而不是过时的DateSimpleDateFormat类来尽可能地模仿您的代码。它走得更顺利。 java.time是现代Java日期和时间API,通常可以更好地使用它。

由于LocalDate是没有时间或时区的日期,因此从一开始就消除了时区差异的问题。 LocalDate.toString()始终在所有设备上提供相同的字符串。另外,LocalDate在没有显式格式化程序的情况下解析相同的字符串。这简直太容易了。

如果您的Android级别不够高,无法在本机使用java.time,请将ThreeTenABP添加到您的项目中,并确保导入org.threeten.bp.LocalDateorg.threeten.bp.format.DateTimeFormatter

您的代码出了什么问题?

Date.toString()用于生成字符串的时区与用于解析日期的格式化程序无关。虽然没有正式记录,但该方法使用JVM的时区设置。我无法保证它可以在您的设备上运行,但至少在我的Mac上我可以通过

控制Date.toString()的结果
    System.setProperty("user.timezone", "Asia/Kolkata");

    System.setProperty("user.timezone", "GMT+05:30");

通过这种方式,我可以获得您从不同设备获得的结果。但是,三个和四个字母的时区缩写是不明确的,通常不是真正的时区,所以不要依赖它们来解析Date.toString()的字符串。 BTW TimeZone.setDefault()具有相同的效果,可能被认为更高级别;只是我养成了避免过时的日期时间课程的习惯,包括TimeZone

链接