【问题标题】:postgres json parse to timestamppostgres json 解析为时间戳
【发布时间】:2016-06-06 08:24:23
【问题描述】:

我正在尝试将一些数据从包含 json 转储的 CSV 文件中获取到我的 postgres 数据库中。只要它只是字符串就可以了,但是我希望包含时间戳的字符串作为时间戳存储在 postgres 中。所以我需要对两个字段进行一些转换:注册日期和出生日期。下面的代码除了日期转换线外都可以工作......

关于如何成功将两个字符串转换为时间戳的任何线索如下:

CREATE TABLE users (
    id SERIAL,
    mongo_id TEXT,
    password VARCHAR(128),
    firstname VARCHAR(200),
    lastname VARCHAR(200),
    dateofbirth TIMESTAMP,
    registerdate TIMESTAMP,
    displayname VARCHAR(200),
    language VARCHAR(200),
    country VARCHAR(200),
    profilepicture VARCHAR(200),
    backgroundpicture VARCHAR(200),
    type VARCHAR(200),
    sex VARCHAR(6),
    offlinemode BOOLEAN,
    email VARCHAR(200),
    friends VARCHAR(255)[]
);

INSERT INTO users (mongo_id, password,firstname,lastname, dateofbirth, registerdate, displayname, language)
SELECT data->>'_id',
 data->>'password',
  data->>'firstName',
   data->>'secondName',
    to_timestamp(data->'dateOfBirth'->>'$date'),   /*<------*/
     to_timestamp(data->'registerDate'->>'$date'), /*<-------*/
      data->>'displayName',
       data->>'language'
FROM import.mongo_users;

mongo_users中的数据格式:

 { "_id" : "1164", "password" : "aaa123123", "firstName" : "Adam", "secondName" : "Kowlalski", "dateOfBirth" : { "$date" : "2014-05-18T07:41:09.202+0200" }, "registerDate" : { "$date" : "2016-06-01T12:59:53.941+0200" }, "displayName" : "Adam Kowlalski", "language" : "nb", "country" : null, "profilePicture" : null, "backgroundPicture" : null, "type" : "USER", "sex" : "MALE", "offlineMode" : true, "email" : "bk_1164@test.email", "friends" : [ "KUE" ] } 

【问题讨论】:

    标签: json postgresql timestamp


    【解决方案1】:

    to_timestamp 函数需要两个参数:文本格式的 date_time 和格式模板。

    您不需要使用 to_timestamp,因为您的日期时间值已经使用有效时间戳进行格式化,并且 PostgreSQL 可以很好地理解 json 格式的时间戳。以下效果很好:

    SELECT data->>'_id',
     data->>'password',
      data->>'firstName',
       data->>'secondName',
        (data->'dateOfBirth'->>'$date')::timestamp, --<< simply cast to timestamp
         (data->'registerDate'->>'$date')::timestamp, --<< simply cast to timestamp
          data->>'displayName',
           data->>'language'
    FROM (SELECT
     '{ "_id" : "1164", "password" : "aaa123123", "firstName" : "Adam", "secondName" : "Kowlalski", "dateOfBirth" : { "$date" : "2014-05-18T07:41:09.202+0200" },
       "registerDate" : { "$date" : "2016-06-01T12:59:53.941+0200" }, "displayName" : "Adam Kowlalski", "language" : "nb", "country" : null, "profilePicture" : null,
       "backgroundPicture" : null, "type" : "USER", "sex" : "MALE", "offlineMode" : true, "email" : "bk_1164@test.email", "friends" : [ "KUE" ] }'::jsonb as data) d
    

    【讨论】:

      【解决方案2】:

      您的 JSON 日期格式类似于 ISO 8601 (https://en.wikipedia.org/wiki/ISO_8601)。要将输入字符串转换为日期变量,您应该使用 to_date 函数。

      例如 to_date(data-&gt;'dateOfBirth'-&gt;&gt;'$date','YYYY-MM-DD"T"HH24:MI:SS')

      请注意,您必须检查时区差异是否起作用。 Postgresql 有一个选项OF: https://www.postgresql.org/docs/current/static/functions-formatting.html

      【讨论】:

      • 请注意,在这种特殊情况下,它还包含时区数据 (+0200),因此该模板将丢弃该信息(尽管在这种特殊情况下它可能是多余的)
      【解决方案3】:

      对我来说,这是有效的。

      SELECT to_timestamp(nullif(LEFT(dates_json->>'date_prop',10), '')::numeric) as date_extracted FROM table_name
      

      首先将值缩小到 10 个符号(如果时间戳包括毫秒),然后检查它是否为空,转换为数字,然后将其传递给函数 to_timestamp()。 这样我修复了另一个错误“日期/时间字段值超出范围”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-30
        • 1970-01-01
        • 1970-01-01
        • 2015-04-02
        • 1970-01-01
        • 1970-01-01
        • 2014-07-03
        相关资源
        最近更新 更多