Java 将检索到的时间戳转换为即时时间会给出错误的日期

Java Converting Retrieved TimeStamp to Instant Gives Wrong Day

提问人:skippy130 提问时间:2/15/2023 最后编辑:Anonymousskippy130 更新时间:2/15/2023 访问量:217

问:

我制作了一个简单的方法,用于将从数据库检索到的时间戳转换为 LocalDate。但是,由于某种原因,我在转换中总是得到错误的日期。我在下面分享了代码。

    private LocalDate getLocalDateFromTimeStamp(Row row, String key){
        return LocalDate.parse(row.getTimestamp(key).toInstant().atZone(ZoneOffset.UTC).toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}

所以我期待的日期是 2022-12-21,但我得到的是 2022-12-22。

当我调试并检查什么时

row.getTimestamp(键)

给我一个对象,这是我所期望的。DateWed Dec 21 20:47:46 CST 2022

当我检查什么时

row.getTimestamp(键).toInstant()

是的,我得到“2022-12-22T02:47:46.299Z”。我认为这就是问题出现的地方,我不确定为什么会发生这种情况。该方法返回的 LocalDate 为“2022-12-22”。

如果有人能对此有所了解,我将不胜感激,因为我不明白为什么会发生这种情况。

时间 java-time localdate

评论

0赞 WJS 2/15/2023
返回什么类型?getTimeStamp(key)
0赞 skippy130 2/15/2023
@WJS 它返回一个 Date 对象。
0赞 Anonymous 2/15/2023
那是哪个班级?土生土长的?我发现返回 .顺便说一句,这是一个设计不佳且早已过时的类,所以如果你可以升级该类以能够返回现代类型,那就去做吧。我确实意识到,就目前而言,这可能只是将您的错误原因转移到其他地方。RowgetTimestamp()Date
0赞 Anonymous 2/15/2023
与时区无关,不是他的问题。让您感到困惑的是它以 UTC 打印。你的错误来自 doing ,它给了你不想要的 UTC 日期,即 12 月 22 日。相反,您需要.当在美国/芝加哥时区运行时,它会给出所需的时区(不知道这是否是您的时区,仅举个例子)。Instant.atZone(ZoneOffset.UTC)return row.getTimestamp(key).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();2022-12-21
0赞 Anonymous 2/15/2023
这回答了你的问题吗?将 java.util.Date 转换为 java.time.LocalDate

答:

2赞 WJS 2/15/2023 #1

试试这个。有关以下参数的详细信息,请查看 DateTimeFormatter

String date = "Wed Dec 21 20:47:46 CST 2022";
  • EEE三个字母的星期几
  • MMM三个字母月份
  • dd整数日
  • HH:mm:ss使用 24 小时制的时间
  • z时区名称 (CST)
  • yyyy
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");
LocalDate dt = LocalDateTime.parse(date, dtf).toLocalDate();
System.out.println(dt);

指纹

2022-12-21

更新

如果您确实有 的实例,您可以尝试以下操作:Date

LocalDate ldt = LocalDate.ofInstant(date.toInstant(), 
    ZoneId.systemDefault());

评论

0赞 skippy130 2/15/2023
谢谢你,这奏效了!如果你有第二个,你能解释一下这种格式,你用来制作 DateTimeFormatter 的模式吗?另外,您知道为什么我拥有的代码会以这种方式运行吗?我不明白为什么它会像这样改变这一天。
0赞 WJS 2/15/2023
我不确定为什么它会添加日期,除非它根据时区调整为不同的默认本地时间。
0赞 skippy130 2/15/2023
我猜是生命的奥秘之一。您能解释一下格式中的“EEE LLL”部分是什么意思吗?我不熟悉它。或者你能给我指出一个资源,在那里我可以学到一点东西吗?
1赞 WJS 2/15/2023
或者你能给我指出一个资源,在那里我可以学到一点东西吗?java.time 包替换了过时的、有缺陷的和相关的遗留类。文档链接在我的回答中。DateDateTimeFormatter
1赞 WJS 2/15/2023
@OleV.V.好的,谢谢你的解释。我把它改成 M。
1赞 Basil Bourque 2/15/2023 #2

TL的;博士

避免不必要的字符串操作。将日期时间类型用于日期时间值。

myResultSet
.getObject( … , OffsetDateTime.class )  // For any database column of a data type akin to the SQL standard type of `TIMESTAMP WITH TIME ZONE`.
.toLocalDate()  // Extract the date portion from the returned `OffsetDateTime` object. 
.toString()     // Generate text in standard ISO 8601 format. 

该类是现在遗留的可怕的日期时间类的一部分。仅使用它们的替代品,即 JSR 310 中定义的现代 java.time 类。Timestamp

而不是 ,用于 JDBC 4.2 及更高版本。对数据类型类似于 SQL 标准类型的任何数据库列执行此操作。TimestampOffsetDateTimeTIMESTAMP WITH TIME ZONE

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

您的问题不清楚,但您似乎希望该时刻的日期部分与UTC的偏移量为零小时-分钟-秒。

检索到的可能已经在 UTC 中。但让我们确定:OffsetDateTime

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;

提取日期部分。

LocalDate localDate = odtUtc.toLocalDate() ;

要生成标准 ISO 8601 格式的文本,请调用 。toString

String output = localDate.toString() ;