[英]SimpleDateFormat.parse(date_string) generate a previous date
I got a weird issue.我有一个奇怪的问题。
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
I call it with:我称之为:
Date date = sdf.parse("06/05/2020");
and it show the "date" is Thu Jun 04 18:00:00 MDT 2020, that is, one day less.它显示“日期”是 Thu Jun 04 18:00:00 MDT 2020,即少了一天。
Where is wrong for SimpleDateFormat? SimpleDateFormat 哪里错了?
I am using Android Studio 3.5.1 and Androidx.我正在使用 Android Studio 3.5.1 和 Androidx。
Thanks in advance.提前致谢。 Shawn肖恩
The bullet-proof way is switching to java.time, the modern Java date and time API.防弹的方法是切换到java.time,现代的Java日期和时间API。
DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("MM/dd/yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse("06/05/2020", dateFormatter);
System.out.println(date);
Output is: Output 是:
2020-06-05 2020-06-05
It's certainly a time zone problem.这当然是时区问题。 However, it isn't reproduced by naïvely running your code.但是,它不会通过天真地运行您的代码来复制。 There is something more going on, and we can only guess at exactly what.还有更多的事情发生,我们只能猜测到底是什么。 I'll present a couple of ways that this might have happened.我将介绍几种可能发生这种情况的方法。
The first possibility, the default time zone of your JVM might have changed underway.第一种可能性,JVM 的默认时区可能正在更改。 To demonstrate:展示:
TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
Date date = sdf.parse("06/05/2020");
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));
System.out.println(date);
Thu Jun 04 18:00:00 MDT 2020 2020 年 6 月 4 日星期四 18:00:00 MDT
In all fairness it's not a full day wrong, it's 6 hours.平心而论,这不是一整天的错误,而是 6 个小时。 It's bad enough, and certainly the day of week and day of month are wrong.这已经够糟糕的了,当然星期几和月份的日期是错误的。 Please note that the JVM's time zone setting may have been changed from a completely different part of your program or from a different program running in the same JVM.请注意,JVM 的时区设置可能已从您程序的完全不同部分或在同一 JVM 中运行的不同程序更改。 What happened was: The SimpleDateFormat
got the default time zone of the JVM, that is, UTC.发生的事情是: SimpleDateFormat
获得了 JVM 的默认时区,即 UTC。 So parsed the date into the first moment of June 5 in UTC.因此,将日期解析为 UTC 时间 6 月 5 日的第一刻。 At this point in time, it's still June 4 in North America.此时,北美仍是 6 月 4 日。 Next, when we print the Date
, Date.toString()
grabs the (changed) time zone of the JVM and uses it for rendering the string.接下来,当我们打印Date
时, Date.toString()
的(更改的)时区并将其用于呈现字符串。 Therefore we got the MDT time (North American Mountain Daylight Time), not the UTC time that had been used for parsing.因此我们得到了 MDT 时间(北美山区夏令时),而不是用于解析的 UTC 时间。
We don't need something as drastic as setting the time zone for the entire JVM to demonstrate, though.不过,我们不需要像为整个 JVM 设置时区那样激烈的东西来演示。 It's enough to set the time zone of the formatter.设置格式化程序的时区就足够了。
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
Date date = sdf.parse("06/05/2020");
System.out.println(date);
When running in America/Edmonton time zone:在美国/埃德蒙顿时区运行时:
Thu Jun 04 18:00:00 MDT 2020 2020 年 6 月 4 日星期四 18:00:00 MDT
What happens is basically the same as above.发生的事情与上面基本相同。
java.time works nicely on both older and newer Android devices. java.time 适用于较旧和较新的 Android 设备。 It just requires at least Java 6 .它只需要至少Java 6 。
org.threeten.bp
with subpackages.并确保从带有子包的org.threeten.bp
导入日期和时间类。java.time
was first described. Java 规范请求 (JSR) 310 ,其中首先描述了java.time
。java.time
to Java 6 and 7 (ThreeTen for JSR-310). ThreeTen Backport 项目, java.time
到 Java 6 和 7 的 backport(ThreeTen for JSR-310)。This is a common problem with TimeZone
, you need to set the correct timezone to your sdf
, something like:这是TimeZone
的常见问题,您需要为sdf
设置正确的时区,例如:
sdf.setTimeZone(TimeZone.getTimeZone("GMT"))
If you set the right timezone, you'll see the right day:)如果您设置了正确的时区,您将看到正确的日期:)
Hope it helps希望能帮助到你
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.