在java中用时区将日期转换为时间戳

aor9mmx1  于 2021-06-29  发布在  Java
关注(0)|答案(3)|浏览(545)

我有一个postgresql数据库,其列定义为timestamp
我收到的是时区格式为yyyy-mm的日期-ddthh:mm:ss.sssx“,例如 2020-12-16T15:05:26.507Z . 如果我想把它插入一个带有timestamp的列,它会抛出“timestamp格式必须是yyyy-mm-dd hh:mm:ss”
我在做什么

Timestamp.valueOf("2020-12-16T15:05:26.507")

现在时区日期来自一个json,所以我现在把它当作一个字符串。
如何将其转换为简单的时间戳格式?至2020-12-16 15:05:26

q9yhzks0

q9yhzks01#

我想你可以使用另一个api的时间戳
静态时间戳值(localdatetime datetime)
并将代码更改为:

LocalDateTime localDateTime = LocalDateTime.parse("2020-12-16T15:05:26.507");
    Timestamp.valueOf(localDateTime);

如果您想使用系统时区以外的其他时区,也可以使用:zoneddatetime
然后使用zoneddatetime获取localdatetime,并将其传递给timestamp.valueof()。

luaexgnf

luaexgnf2#

两条建议:
因为您收到的字符串包含utc指示符( Z ),将utc时间保存到数据库中。如果允许,请将postgresql数据库中的数据类型更改为 timestamp with time zone 为此目的。
使用java.time,现代的java日期和时间api。不要将日期和时间也保存为 Timestamp 也不是作为一个 String 到数据库。这个 java.sql.Timestamp 类的设计很差,是在已经设计很差的基础上的一个真正的黑客 java.util.Date 类,而且早已过时。
从json得到的字符串是iso8601格式的。这很好,因为它是一个国际标准,而且java.time的类通常以本机方式解析iso8601格式,也就是说,没有任何显式的格式化程序。要解析它:

String fromJson = "2020-12-16T15:05:26.507Z";
    OffsetDateTime dateTime = OffsetDateTime.parse(fromJson);
    System.out.println(dateTime);

目前产量:
2020-12-16t15:05:26.507z OffsetDateTime 同时打印iso 8601格式。插入postgress:

String sql = "insert into your_table(your_timestamp_with_time_zone_col)"
            + " values(?);";
    PreparedStatement ps = yourDatabaseConnection.prepareStatement(sql);
    ps.setObject(1, dateTime);
    int rowsInserted = ps.executeUpdate();

如果无法更改数据库中的数据类型,则需要插入 LocalDateTime 进入你的 timestamp (不带时区)列:

LocalDateTime dateTime = OffsetDateTime.parse(fromJson)
            .atZoneSameInstant(ZoneOffset.UTC)
            .toLocalDateTime();

    String sql = "insert into your_table(your_timestamp_col) values(?);";

其余和以前一样。
为了以防万一,我选择了转换成utc。在您的示例中,字符串已经是utc格式,因此转换为no操作;但可能并不总是这样,所以最好这样做。

链接

oracle教程:date time解释如何使用java.time。

xa9qqrwz

xa9qqrwz3#

下表总结了 PostgreSQL 列类型Map Java SE 8 日期时间类型:

--------------------------------------------------
PostgreSQL                          Java SE 8
==================================================
DATE                                LocalDate
--------------------------------------------------
TIME [ WITHOUT TIMEZONE ]           LocalTime
--------------------------------------------------
TIMESTAMP [ WITHOUT TIMEZONE ]      LocalDateTime
--------------------------------------------------
TIMESTAMP WITH TIMEZONE             OffsetDateTime
--------------------------------------------------

请注意 ZonedDateTime , Instant 以及 OffsetTime / TIME [ WITHOUT TIMEZONE ] 不支持。另外,请注意 OffsetDateTime 示例必须在 UTC (其时区偏移为 +00:00 小时)。这是因为后端将它们存储为 UTC .
因此,有两种选择。

选项1(推荐):

将列类型更改为 TIMESTAMP WITH TIMEZONE . 建议这样做,因为您的日期时间字符串 Z 代表什么 Zulu 日期时间或 UTC 日期时间。使用 OffsetDateTime ,您可以解析此日期时间字符串,而不需要任何 DateTimeFormatter 明确地。
演示:

import java.time.OffsetDateTime;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.parse("2020-12-16T15:05:26.507Z");
        System.out.println(odt);
    }
}

输出:

2020-12-16T15:05:26.507Z

下面给出了一个如何使用它的例子 OffsetDateTime 对于db crud操作:

OffsetDateTime odt = OffsetDateTime.parse("2020-12-16T15:05:26.507Z");
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);
st.executeUpdate();
st.close();

选项2:

如果仍要保持列类型为 TIMESTAMP [ WITHOUT TIMEZONE ] ,您可以获得 LocalDateTimeOffsetDateTime 使用方法如下:

OffsetDateTime odt = OffsetDateTime.parse("2020-12-16T15:05:26.507Z");
LocalDateTime ldt = odt.toLocalDateTime();
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, ldt);
st.executeUpdate();
st.close();

相关问题