import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// I have created this instance of LocalDateTime for the purpose of demo. This
// should come from your ResultSet
LocalDateTime ldt = LocalDateTime.parse("2020-12-15 17:38:40.962",
DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS"));
OffsetDateTime odt = ldt.atOffset(ZoneOffset.UTC);
System.out.println(odt);
// Convert the odt to Zone
ZoneId zoneId = ZoneId.of("Europe/Vatican");
ZonedDateTime zdt = odt.atZoneSameInstant(zoneId);
System.out.println(zdt);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuMMddHHmmssXX");
System.out.println(zdt.format(dtf));
}
}
2条答案
按热度按时间s4n0splo1#
您应该将日期和时间检索到
LocalDate
对象如下所示:然后转换
ldt
变成一个OffsetDateTime odt
使用LocalDateTime#atOffset
. 最后,转换odt
进入ZonedDateTime
同时使用odt.atZoneSameInstant
你必须通过ZoneId
作为论据。ZonedDateTime
设计用于自动处理由于夏季/冬季变化引起的时间变化。最后,使用适当的
DateTimeFormatter
以所需格式打印日期和时间。演示:
输出:
如何快速演示
ZonedDateTime
自动调整时区偏移:输出:
8gsdolmq2#
java.sql.Timestamp
表示太阳光时间:独立于时区或时区政治变化的时刻。将其呈现为20201218064312+0800
因此是不可能的;时间戳对象中没有足够的信息来执行此操作。转换为预约时间第一,这是很容易的。
太阳光时间是一个独立于政治或地点的时刻。从现在起正好x秒就发生了。时区或地区变动的政治法令、夏时制等,没有任何效力。以毫秒表示;天、月、年等在这里毫无意义。代表人
Instant
.约会时间是人类倾向于做的事情,并且尽可能具体。以年、月、日和时区表示。请注意
+0800
不是一个时区,也不是一个有用的时区,也不是任何人都可以预约的时区。Europe/Amsterdam
,那是时区。这是用来预约的:如果我打电话给我的理发师,预约下周二的08:00
,您应该将其存储为约会时间。这一点很重要:如果为我的理发师所在的地点决定时间的政治实体决定我们今年不会在短时间内实行夏时制,那就意味着我的约会实际上是提前一个小时或晚一个小时的绝对时间(solarflares)。这就是日光浴和预约时间的区别。代表人ZonedDateTime
.闹钟时间是您配置闹钟的方式。就预约时间而言,如果我从欧洲飞到美国,我的理发师预约前的绝对秒数不会改变。然而,如果我设置闹钟是因为我想在早上8点起床,那就改变了“早上8点”现在不同了。代表人
LocalDate
,LocalTime
,和LocalDateTime
.这个
j.u.Date
以及j.u.Calendar
API是愚蠢的,不要使用它们:他们没有意识到时间以3种不同的方式工作,并将3种方式混为一谈。这意味着这些方法毫无意义(在dateapi的情况下,它们都被弃用了,因为它们毫无意义)并且给出了错误的答案。因此,不要使用它们。使用java.time
api,唯一有意义的。如果你不能,例如jdbc规范强迫你使用蹩脚的api,那么尽快转换成java.time,并首先转换成3种表示形式中正确的一种,然后再进行转换。要得到的关键是j.s.timestamp是一个solarflares时间(也是如此)
j.u.Date
-是的,这是史诗般的命名错误)。有效的话,你要求把太阳花的时间20201218064312+0800
,这很奇怪,因为太阳光时间与“月”、“日”、“年”和“时区”的概念不太一致。预约时间在这方面要好得多,因此,先转换到那个时间,然后就很容易了。因此,公式为:将timestamp转换为最合适的java.time类型,即
Instant
(因为从技术上讲,时间戳的实现方式是:从epoch开始的毫秒+该毫秒中的纳米)将您的瞬间转换为zoneddatetime,因为您想要的呈现包括瞬间无法理解的概念:人类的概念,如“月”。
将您的zdt转换为所需位置的zdt。Instant不包含任何位置/区域的概念,因此您需要显式指定您想要的奇怪的、从未被人类使用过的对象
+0800
因为一些奇怪的原因。使用datetimeformatter格式化正确定位的zdt。
你确定你想要+0800吗?我打赌你想
Asia/Singapore
或者类似的,不是吗+0800
,然后把它呈现成这样,尽管,真的,你不应该这样做,当国家决定改变区域时,它会变得混乱,他们总是这样做。比如说+0800
是错过理发预约的好方法。nb2:上面的第2步和第3步可以在一个步骤中完成,但最好是意识到你在把事情结合起来。