我有UTC日期,我需要创建与UTC值完全相同的Date对象(旧有原因)。
我设法做到了:
String date = "2012-05-05 12:13:14";
TemporalAccessor formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.of("UTC"))
.parse(date);
Instant instant = Instant.from(
formatter
); //
ZonedDateTime zdf = ZonedDateTime.ofInstant(instant,ZoneId.of("UTC"));
Calendar calendar = Calendar.getInstance();
calendar.set(zdf.getYear(),zdf.getMonthValue(),zdf.getDayOfMonth(),zdf.getHour(),zdf.getMinute(),zdf.getSecond());
Date dt = calendar.getTime();
Date d2 = Date.from(instant);
但是,什么困扰着我-
当我创建日期对象时,它应该在JVM的默认时区中显示日期。但是这里dt
与我输入的UTC日期具有完全相同的值,但是dt2
具有默认时区中表示的相同日期,为什么会发生这种情况?为什么一个不转换而另一个不转换?
感谢您的解释!
答案 0 :(得分:1)
我将一一解释中心线。
Calendar calendar = Calendar.getInstance();
这将创建一个Calendar
,其时区与JVM的默认时区相同。与Date
不同,Calendar
有一个时区。
calendar.set(zdf.getYear(),zdf.getMonthValue(),zdf.getDayOfMonth(),
zdf.getHour(),zdf.getMinute(),zdf.getSecond());
这会将您的Calendar
设置为与ZonedDateTime
相同的挂钟时间,即12:13:14。由于ZonedDateTime
和Calendar
具有不同的时区(分别为UTC和您的本地时区),因此会产生不同的时刻。
@VGR也正确:ZonedDateTIme
的日期为5月(第5个月),但您将Calendar
的月份设置为6月,因为Calendar
的月份令人困惑,0-从1月的0到12月的11。
Date d2 = Date.from(instant);
这是从Instant
到Date
的正确转换,并为您提供与Instant
相同的时间点和相同的时刻。因此,不是与Calendar
和dt
相同的时刻。
您的问题中可能已经理解了这一点,但是对于那些一直阅读的人,我想直接声明:Date
和Calendar
的设计很差,已经过时了。除非有必要与无法更改或不想立即升级的旧版API交互时,否则不要使用它们。对于其他所有用途,请遵循现代的Java日期和时间API java.time。
答案 1 :(得分:1)
java.util.Date
代表UTC的时刻。它的toString
方法在生成格式不正确的字符串时动态地应用JVM的当前默认时区,从而为您带来好处。 很多原因之一是从不使用此类。Date
和Calendar
。现在应避免使用它们legacy。Answer by Ole V.V.是正确的,应该接受。我会加一些想法。
您正在将可怕的旧式日期时间类(Date
,Calendar
)与它们的现代替代品(Instant
,ZonedDateTime
)混合在一起。 请勿混用。通过使用JSR 310, java.time 类完全取代了旧类。
无需再使用Date
或Calendar
。 不要浪费时间尝试理解它们。替换它们是有原因的-实际上有很多原因。用你的大脑和时间进行更有成效的工作。
如果必须使用旧类与尚未更新为 java.time 的旧代码进行互操作,请通过调用新的to…
/ {{1}来回转换}转换方法已添加到旧类中。使用 java.time 类执行业务逻辑,数据交换和数据存储。
from…
类被java.util.Date
替换。
Instant
java.util.Date d = Date.from( instant ) ; // From modern to legacy.
Instant instant = d.toInstant() ; // From legacy to modern.
类或其更常用的子类GregorianCalendar
被Calendar
取代。假设您的ZonedDateTime
对象实际上是下面的Calendar
,则可以进行投射然后进行转换。
GregorianCalendar
这是一张将旧类映射到现代类的图表。