【发布时间】:2019-09-07 15:36:13
【问题描述】:
我收到一个代表 UTC 日期时间的日期。让我们说: 2019 年 6 月 21 日 10:00
我想将此日期时间转换为时区“欧洲/维也纳”,期望: 2019 年 6 月 21 日 12:00
我不明白,为什么我下面的代码显示的时间相同
Date utcFinish = new Date(new Date().getYear(), Calendar.JUNE, 21);
TimeZone europeVienna = TimeZone.getTimeZone("Europe/Vienna");
Calendar finishInViennaTime = Calendar.getInstance(europeVienna);
finishInViennaTime.setTime(utcFinish);
System.out.println(format.format(utcFinish));
System.out.println(format.format(finishInViennaTime.getTime()));
输出:
2019-06-21 00:00
2019-06-21 00:00
什么是最好的仅限 java7(没有 joda,localdate pls)解决方案!?谢谢
编辑:我也试过了:
SimpleDateFormat formatWithTimezone = new SimpleDateFormat("yyyy-MM-dd HH:mm");
formatWithTimezone.setTimeZone(TimeZone.getTimeZone("Europe/Vienna"));
SimpleDateFormat formatonly = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date utcDate = new Date(new Date().getYear(), Calendar.JUNE, 21);
System.out.println(formatonly.format(utcDate));
System.out.println(formatWithTimezone.format(utcDate));
输出:
2019-06-21 00:00
2019-06-21 00:00
解决方案
感谢所有解决方案。最后的问题是默认时区。这是我目前的解决方案(欢迎提供更多反馈!):
// Unfortunately this date has the wrong time zone (Local Time Zone),
// because Date assumes Local Time Zone the database stores timestamps
// in utc that's why I now convert to a datestring and reparse
Date finishTimeWrongTimeZone = new Date(new Date().getYear(), Calendar.JUNE, 21);
// in reality i call the db here like getFinishTime();
// get the plain date string without time shifting
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MMM-dd HH:mm");
String dateWithoutTimeZone = formatter.format(finishTimeWrongTimeZone);
// add the timezone to the formatter and reinterpret the datestring
// effectively adding the correct time zone the date should be in
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String finishTime = null;
try {
Date dateWithCorrectTimeZone = formatter.parse(dateWithoutTimeZone);
// Convert to expected local time zone (europe/vienna)
formatter.setTimeZone(TimeZone.getTimeZone("Europe/Vienna"));
finishTime = formatter.format(dateWithCorrectTimeZone);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(finishTime);
【问题讨论】:
-
日期没有时区。从概念上讲,它是一个瞬间(它只在 Unich Epoch 之后包装几毫秒),无论您身在何处。仅当将其表示为 String 时,您才附加时区,因此 DateFormat 对象的工作是进行转换。
-
@Shakka,上述 spi 的评论正是为什么你的“没有 joda 或 localdate”的方法是错误的。这些新的做事方式之所以存在,正是因为旧版 JDK 日期类型至少命名不佳,并且难以正确使用。
-
旁注:数据类已过时,设计不佳,如果可能,某些方法已弃用,请使用 java.time api、ZonedDateTime 类和您的案例 getYear() 已弃用
-
很确定
new Date(...)(顺便说一句已弃用)会生成本地时区的时间,而不是UTC。 -
@TiiJ7,如上所述,
java.util.Date只是纪元以来的毫秒数,因此实际上并不包含任何时区信息。但是,该特定构造函数确实使用默认系统时区来推断如何将小时-分钟值(在本例中为 0-0)转换为纪元秒值。