【问题标题】:Json response to postgresql datetime conversion Java postgresqlJson响应postgresql日期时间转换Java postgresql
【发布时间】:2019-02-09 18:52:09
【问题描述】:

我正在获取日期时间字段的 JSON 响应,如下所示: /Date(1534291200000)/ 和 PT12H18M02S

 SELECT     CAST('ClearingDate' AS TIMESTAMP) from testdata;

在使用 CAST 函数或 to_timestamp 时出现以下错误:

错误:时间戳类型的输入语法无效:“/Date(1534291200000)/” SQL 状态:22007

如何使用 postgresql 将其转换为时间戳?如果不是 postgresql,有没有办法在 Java 中这样做?

【问题讨论】:

标签: java json postgresql datetime timestamp


【解决方案1】:

在PostgreSQL中直接转换的解决方案:

to_timestamp(CAST(SUBSTRING (CAST(Clearingdate AS varchar), 9, 10) AS NUMERIC))
from date_test;

我终于明白了。非常感谢您的所有意见。

【讨论】:

  • 它会在 2001 年 9 月 9 日之前给出不正确的结果,因为会有更少的数字。无论如何,感谢您发布解决方案。它会忽略毫秒(秒的分数),但在你的例子中,无论如何它都是 0,所以没有任何区别。
  • 感谢您的回复。但我得到的结果是 '2018-07-31 19:00:00-05' 大于 2001 年 9 月 9 日,也在该特定值的正确范围内。
  • 2018-07-31 19:00:00-05 与 2018-08-01 00:00:00 UTC 的时间点相同,只是表示为 UTC 偏移处的日期和时间 - 05:00(这就是最后的 -05 的意思)。那会是正确的吗? (在 2001 年提到的日期之前,您会得到通常非常遥远的结果。)
  • 是的,没错。纪元值 1534291200000 为 2018-08-15 00:00:00 UTC,1533081600000 为 '2018-07-31 19:00:00-05',这是预期的结果。此外,您使用 Java 发表的以下帖子也提供了相同的答案。非常感谢。
  • 你知道这是什么格式吗? PT12H18M02S 以及如何在 postgreSQL 或 Java 上将其转换为枯萎?
【解决方案2】:

使用时间戳(导入 java.sql.Timestamp)

String fromJson = "/Date(1534291200000)/";
String ts = fromJson.substring(6, fromJson.length()-2);
Long tsInMillisSec = Long.parseLong(ts);
Timestamp ts = new Timestamp(tsInMillisSec);

【讨论】:

  • 时间戳不起作用 json 响应包含关键字 Date。
  • 这是响应的示例输出:/Date(1534291200000)/
  • 您能否添加更多您收到的示例 json 响应?
  • 我在日期列中得到一个日期列表,如下所示:'/Date(1534809600000)/''/Date(1531785600000)/''/Date(1534809600000)/''/Date(1534809600000 )/' '/Date(1535328000000)/' '/Date(1534896000000)/' '/Date(1531440000000)/' 我需要将其转换为postgresql时间戳
  • 尝试java子字符串String fromJson = "/Date(1534291200000)/"; String ts = fromJson.substring(6, fromJson.length()-2); Long tsInMillisSec = Long.parseLong(ts);
【解决方案3】:

抱歉,我不知道如何在 PostgreSQL 中执行此操作。在 Java 中:

    String timestampString = "/Date(1534291200000)/";
    String millisString = timestampString.replaceFirst("^/Date\\((\\d+)\\)/$", "$1");
    Instant inst = Instant.ofEpochMilli(Long.parseLong(millisString));
    System.out.println(inst);

输出是

2018-08-15T00:00:00Z

我正在使用正则表达式来验证字符串的语法并仅取出数字的子字符串。这个数字表示自纪元以来的毫秒数。 java.time 中的 Instant 类,现代 Java 日期和时间 API,是用于时间戳的正确类(忘记过时的 Timestamp 类,我们不再需要它了)。

如果您需要将其存储回 PostgreSQL:

    PreparedStatement stmt = yourConnection.prepareStatement(
            "insert into your_table(your_timestamp_column) values (?);");
    stmt.setObject(1, inst);

请根据您的数据库设计和情况进行修改。

链接:Oracle tutorial: Date Time解释如何使用java.time

【讨论】:

    【解决方案4】:

    java.time

    java.util 的日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,转用modern date-time API

    Instant#ofEpochMilli

    这里的关键是在给定字符串的毫秒数内得到Instant 的对象。拥有Instant 后,您可以将其转换为其他java.time types,例如ZonedDateTime 甚至是旧版java.util.Date

    关于正则表达式 \D+ 的注释:\D 指定 non-digit,而 + 指定其出现的 one or more

    演示:

    import java.time.Instant;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String text = "/Date(1534291200000)/";
            // Replace all non-digits i.e. \D+ with a blank string
            Instant instant = Instant.ofEpochMilli(Long.parseLong(text.replaceAll("\\D+", "")));
            System.out.println(instant);
    
            // Now you can convert Instant to other java.time types e.g. ZonedDateTime
            // ZoneId.systemDefault() returns the time-zone of the JVM. Replace it with the
            // desired time-zone e.g. ZoneId.of("Europe/London")
            ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
            // Print the default format i.e. the value of zdt#toString
            System.out.println(zdt);
    
            // A custom format
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMMM dd HH:mm:ss uuuu", Locale.ENGLISH);
            String strDateTimeFormatted = zdt.format(dtf);
            System.out.println(strDateTimeFormatted);
        }
    }
    

    输出:

    2018-08-15T00:00:00Z
    2018-08-15T01:00+01:00[Europe/London]
    Wed August 15 01:00:00 2018
    

    如何从Instant 获取java.util.Date

    您应该避免使用java.util.Date,但无论出于何种目的,如果您想获得java.util.Date,您所要做的就是使用Date#from,如下所示:

    Date date = Date.from(instant);
    

    PT12H18M02S 呢?

    您可以将其解析为java.time.Duration,它以ISO-8601 standards 为模型,并作为JSR-310 implementation 的一部分与Java-8 一起引入。

    如果您浏览过上述链接,您可能已经了解到PT12H18M02S 指定的持续时间为 12 小时 18 分 2 秒,您将其添加到日期时间对象(例如上面获得的zdt)以获得一个新的日期时间。

    Duration duration = Duration.parse("PT12H18M02S");
    ZonedDateTime zdtUpdated = zdt.plus(duration);
    System.out.println(zdtUpdated);
    

    输出:

    2018-08-15T13:18:02+01:00[Europe/London]
    

    Trail: Date Time 了解现代日期时间 API。

    如何在 JDBC 中使用java.time 类型?

    PostgreSQL™ JDBC 驱动程序使用 JDBC 4.2 实现对 Java 8 日期和时间 API (JSR-310) 的原生支持。

    请注意,不支持 ZonedDateTimeInstantOffsetTime / TIME [ WITHOUT TIMEZONE ]。另外,请注意所有OffsetDateTime 实例都必须在UTC 中(偏移量为0)。这是因为后端将它们存储为UTC

    OffsetDateTime odt = zdt.withZoneSameInstant(ZoneOffset.UTC).toOffsetDateTime();
    PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
    st.setObject(1, odt);
    st.executeUpdate();
    st.close();
    

    【讨论】:

      【解决方案5】:

      这可能有效:

      select cast(cast('{"dtJson":"2020-10-23 13:40:54"}'::json->'dtJson' as varchar) as timestamp);
      

      【讨论】:

        猜你喜欢
        • 2011-09-02
        • 1970-01-01
        • 2021-04-07
        • 2018-03-28
        • 2019-07-23
        • 2020-01-16
        • 2014-02-25
        • 2023-03-28
        • 2016-03-25
        相关资源
        最近更新 更多