如何使用java将ja.sql.timestamp转换为给定的格式



在数据库中以UTC时区存储时间。从数据库获取后需要将时间转换为给定格式"20201218064312+0800">

这里+也应该照顾夏天的时间。

您应该将日期时间检索到LocalDate对象中,如下所示:

LocalDate ldt = rs.getObject(1, LocalDate.class));

然后使用LocalDateTime#atOffsetldt转换为OffsetDateTime odt。最后,使用odt.atZoneSameInstantZoneId作为参数,将odt转换为具有相同时刻的ZonedDateTimeZonedDateTime被设计为自动处理由于夏季/冬季变化而导致的时间变化。

最后,使用适当的DateTimeFormatter以所需的格式打印日期时间。

演示:

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));
}
}

输出:

2020-12-15T17:38:40.962Z
2020-12-15T18:38:40.962+01:00[Europe/Vatican]
20201215183840+0100

ZonedDateTime如何自动调整时区偏移量的快速演示:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
LocalDateTime ldtSummer = LocalDateTime.of(2017, 06, 02, 6, 0, 0);
LocalDateTime ldtWinter = LocalDateTime.of(2017, 12, 02, 6, 0, 0);
ZoneId nyZone = ZoneId.of("America/New_York");
ZonedDateTime nyZdtSummer = ldtSummer.atZone(nyZone);
ZonedDateTime nyZdtWinter = ldtWinter.atZone(nyZone);
System.out.println(nyZdtSummer);
System.out.println(nyZdtWinter);
}
}

输出:

2017-06-02T06:00-04:00[America/New_York]
2017-12-02T06:00-05:00[America/New_York]

java.sql.Timestamp表示太阳耀斑时间:与时区或时区的政治变化无关的时间时刻。因此,将其呈现为20201218064312+0800是不可能的;没有足够的信息包含在该时间戳对象中,无法执行此操作。

首先转换为约会时间,从那里很容易。

  • 太阳耀斑时间是一个独立于政治或地点的时刻。它发生/将在从现在起正好 X 秒发生。时区或区域更改、夏令时等的政治法令对任何影响为零。以毫秒为单位;天、月、年等在这里毫无意义。以Instant.

  • 约会时间是人类倾向于做时间的方式,并且尽可能具体。以年、月、日和时区表示。请注意,+0800不是时区,无论如何都不是有用的时区,也不是任何人约会过的区域。Europe/Amsterdam,这是一个时区。这用于约会:如果我打电话给我的理发师并预约下周二08:00,您应该将其存储为约会时间。这一点很重要:如果决定我的理发师所在地点的时间的政治实体决定我们今年不会在短时间内进行夏令时,这意味着我的约会现在实际上提前或晚了一个小时绝对(太阳耀斑)时间。这就是太阳耀斑和约会时间之间的区别。以ZonedDateTime为代表。

  • 闹钟
  • 时间是您倾向于配置闹钟的方式。随着预约时间,如果我从欧洲飞往美国,我的理发师预约之前的绝对#秒数不会改变。但是,如果我因为想在早上 8 点起床而设置闹钟,那确实会改变;"早上8点"现在不同了。由LocalDateLocalTimeLocalDateTime表示。

  • j.u.Datej.u.CalendarAPI 是愚蠢的,不要使用它们:他们没有意识到时间以 3 种不同的方式工作,并将所有 3 种方式混为一谈。这意味着这些方法毫无意义(在日期 API 的情况下,它们都被弃用,因为它们没有意义)并给出错误的答案。因此,不要使用它们。使用java.timeAPI,这是唯一有意义的 API。如果你不能,因为例如JDBC规范强制你使用蹩脚的API,请尽快转换为java.time,并首先转换为3种表示形式中的正确一种,然后进行转换。

关键是j.s.Timestamp是一个太阳耀斑时间(j.u.Date也是如此 - 是的,它被史诗般的错误命名)。实际上,您要求将太阳耀斑时间转换为20201218064312+0800,这很奇怪,因为太阳耀斑时间与"月","天","年"和"时区"的概念不太兼容。约会时间要好得多,因此,首先转换为那个,然后很容易。因此,公式为:

  1. 将时间戳转换为最合适的java.time类型,这是Instant(因为从技术上讲,时间戳的实现方式是:millis-since-epoch+nanos-in-that-milli)
  2. 将即时转换为 ZonedDateTime,因为您想要的渲染包括即时无法理解的概念:人类概念,如"月"。
  3. 将 ZDT 转换为所需位置的 ZDT。瞬间不包括任何位置/区域的概念,因此为什么你需要明确指定你想要奇怪的,从未被人类使用的奇怪+0800区域,出于某种奇怪的原因。
  4. 使用日期时间格式化正确定位的 ZDT。

注1: 你确定要+0800吗?我敢打赌你想要Asia/Singapore或类似的东西,而不是+0800,然后像这样渲染,虽然,真的,你不应该那样做,当国家决定切换区域时会感到困惑,他们一直在这样做。陈述诸如+0800之类的事情是错过理发师约会的好方法。

注意2:上面的步骤2和3可以在一个步骤中完成,但很高兴意识到你正在组合事情。

最新更新