问题描述
我在从外部系统接收的持久存储中有日期时间。我需要使用它并将其设置为 Java 库例程的日期类型。这混淆了在当前 jvm 时区下设置的相同内容。我知道偏移量不一定对应时区,但是,这会搞砸很多事情。
例如:
2020-08-14T08:59:34.961+05:30
示例代码:
String dateFromDatabase = "2020-08-14T08:59:34.961+05:30";
SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date tempDate=outputDateFormat.parse(dateFromDatabase);
System.out.println( tempDate );
示例输出:
Thu Aug 13 23:29:34 EDT 2020
预期输出:
it should not return the EDT based datetime
如何使用正确的偏移量保持我的日期?
关于如何实现这一目标有任何建议吗?
谢谢
解决方法
java.util.Date
对象不是像 modern date-time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即 January 1,1970,00:00:00 GMT
(或 UTC)。这意味着无论世界上的位置如何,Date
对象都表示相同的数字(从纪元开始的毫秒数)。当您打印 java.util.Date
的对象时,它的 toString
方法返回 JVM 时区中的日期时间,从这个毫秒值计算出来。为了在不同的时区打印日期时间,我们将时区设置为 SimpleDateFormat
并从中获取格式化的字符串。
如果您不喜欢 Thu Aug 13 23:29:34 EDT 2020
这样的输出,它是 Date#toString
在您所在的时区返回的字符串(并且在不同的时区会有所不同),有两种选择:
- 表示使用
Date#getTime
获得的以毫秒为单位的Date
(如上所述,它在世界上的任何位置都是相同的)。 - 保留原始字符串
2020-08-14T08:59:34.961+05:30
原样,因为它已经表示 ISO8601 format 中的日期时间。
请注意,java.util
日期时间 API 及其格式 API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern date-time API*。
现代日期时间 API 的演示:
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Date;
public class Main {
public static void main(String args[]) {
String dateFromDatabase = "2020-08-14T08:59:34.961+05:30";
ZonedDateTime zdt = ZonedDateTime.parse(dateFromDatabase);
System.out.println(zdt);
// If at all you need java.util.Date,you can get it from Instant
Instant instant = zdt.toInstant();
Date date = Date.from(instant);
}
}
输出:
2020-08-14T08:59:34.961+05:30
从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。