【问题标题】:Turn postgres date representation into ISO 8601 string将 postgres 日期表示转换为 ISO 8601 字符串
【发布时间】:2016-12-14 12:18:40
【问题描述】:

我正在尝试将 Postgres 日期表示格式化为 ISO 8601 字符串。我假设有一个 Postgres 函数可以做到这一点,但我发现文档中的示例很短。

我的查询是

SELECT
  now()::timestamp

返回

[{{2016, 8, 9}, {3, 56, 55, 754181}}]

我正在尝试将日期转换为看起来更像的格式 2016-8-9T03:56:55+00:00

我需要对查询进行哪些更改才能做到这一点?感谢您的帮助。

【问题讨论】:

  • 发布到 Stack Overflow 时,请让您的示例场景和代码尽可能简短。您的复杂查询与格式化日期时间的问题无关。选择当前时刻的一行就足以证明问题。
  • @BasilBourque 我已经简化了。
  • 指定您使用什么软件连接/查询 PostgreSQL 的信息/标签。

标签: postgresql date elixir iso8601 ecto


【解决方案1】:

我想我找到了一种进行格式化的方法,但这并不理想,因为我正在自己编写格式化。

这是一个潜在的解决方案:

SELECT to_char (now()::timestamp at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')

【讨论】:

  • 这种形式不起作用,至少在 PG10 中是这样。 ::timestamp 删除时区信息,'at timezone UTC' 再次移动偏移量,所以你移动它两次。 (now() 在时区 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"');确实有效
  • 在我的情况下,我也需要毫秒,因此您只需要在几秒后添加 .MS 即可。 to_char (now()::timestamp at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
  • 为了让它工作,我需要将 now() 转换为 timestamptz 而不是 timestamp
【解决方案2】:

这是“将 PostgreSQL 日期表示转换为 ISO 8601 字符串”的简洁方法:

SELECT to_json(now())#>>'{}'

它使用#>> 运算符和to_json() 函数,两者都可以在此页面上找到: https://www.postgresql.org/docs/current/functions-json.html

运算符“将指定路径处的 JSON 对象作为文本获取”。但是,当您指定一个空数组文字 '{}' 作为路径时,它指定了根对象。

将此方法与类似方法进行比较:

SELECT
to_char(now(), 'YYYY-MM-DD"T"HH24:MI:SSOF') AS most_lengthy, -- See note: *
trim(both '"' from to_json(now())::text) AS a_bit_lengthy,
to_json(now())::text AS unwanted_quotes,
to_json(now())#>>'{}' AS just_right

它更短,但产生相同的结果。

* 此外,JavaScript 不会通过 Date() 构造函数解析第一个方法的输出,因为它需要一个 simplification of the ISO 8601 ,它只接受 (+/-)HH:mmZ 格式,但OF 返回不带分钟的 (+/-)HH 格式,除非输入时区是一小时的一小部分,例如在会话开始时使用SET timezone=-4.5;。或者,您可以手动将您的时区作为字符串附加到冗长的版本中,并排除 OF

【讨论】:

  • 非常感谢。出于我自己的目的,我正在处理“TIMESTAMP WITHOUT TIMEZONE”类型,我想将其强制为 UTC,因此我通过像这样附加“Z”字符来增强此解决方案:to_json(my_column)#>>'{}' || 'Z'
【解决方案3】:

也许对于某些人来说,知道因为 Postgres 9.4 to_json 函数(以及 row_to_json)也将时间戳转换为正确的 ISO 8601 格式,但另外它在引号中包装了一个值,这可能会有所帮助可取的:

SELECT now();
  2017-05-10 15:57:23.736054+03

SELECT to_json(now());
  "2017-05-10T15:57:23.769561+03:00"

-- in case you want to trim the quotes
SELECT trim(both '"' from to_json(now())::text);
  2017-05-10T15:57:23.806563+03:00

【讨论】:

  • to_json(now()) 在 Postgres 9.3 中没有 T
  • @cdmckay,感谢您指出这一点,我添加了答案:“自 9.6 以来”虽然我没有尝试在 9.5 和 9.4 中运行查询。
  • 9.4和9.5都可以,只有9.3有T怪
  • 知道了,修正了描述,再次感谢@cdmckay
  • PG9.4+ 的绝佳答案
【解决方案4】:

timezone 会话变量设置为您希望输出所在的任何时区,然后使用to_char(now(), 'YYYY-MM-DD"T"HH24:MI:SSOF')

如果您使用at time zone '...',请注意这将删除任何时区信息,并假设用户已经知道时区。

如果您使用at time zone 'UTC',则输出应始终为 UTC 时间,并带有正确的时区信息(无偏移)。

set timezone='UTC';


select to_char(now(), 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T02:02:26+00  /* UTC time */


select to_char(now() at time zone 'Australia/Sydney', 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T13:02:26+00  /* Local Sydney time, but note timezone is incorrect. */


set timezone='Australia/Sydney';


select to_char(now(), 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T13:02:26+11  /* Local Sydney time with correct time zone! */


select to_char(now() at time zone 'Australia/Sydney', 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T13:02:26+00  /* Still local Sydney time, but time zone info has been removed. */


select to_char(now() at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T02:02:26+00  /* Correct UTC time with correct offset. */

This blog post给出了相当详细的解释。

【讨论】:

    【解决方案5】:

    只有功能对我有用,因为您需要设置时区。

    要具有带区域的默认值时区:

    create table somedata (
      release_date timestamptz DEFAULT NOW()
    )
    

    创建function:

    CREATE OR REPLACE FUNCTION date_display_tz(param_dt timestamp with time zone)
     RETURNS text AS
    $$
    DECLARE var_result varchar;
    BEGIN
    PERFORM set_config('timezone', 'UTC', true);
    var_result := to_char(param_dt , 'YYYY-MM-DD"T"HH24:MI:SS:MS"Z"');
    RETURN var_result;
    END;
    $$ language plpgsql VOLATILE;
    

    然后输出:

    # SELECT
    #   localtimestamp, current_timestamp,
    #   to_char(localtimestamp, 'YYYY-MM-DD"T"HH24:MI:SS:MS"Z"'),
    #   to_char(current_timestamp, 'YYYY-MM-DD"T"HH24:MI:SS:MS"Z"'),
    #   date_display_tz(localtimestamp), date_display_tz(current_timestamp);
             timestamp          |              now              |         to_char          |         to_char          |     date_display_tz      |     date_display_tz
    ----------------------------+-------------------------------+--------------------------+--------------------------+--------------------------+--------------------------
     2017-04-27 23:48:03.802764 | 2017-04-27 21:48:03.802764+00 | 2017-04-27T23:48:03:802Z | 2017-04-27T23:48:03:802Z | 2017-04-27T21:48:03:802Z | 2017-04-27T21:48:03:802Z
    (1 row)
    

    也请看this

    如果您希望服务器返回各自的时区信息 另一个时区,我相信你需要使用 SET TIME ZONE。 否则,服务器会自动(转换时间戳)和 返回服务器的时区。

    test=# select (current_timestamp at time zone 'UTC') at time zone 'UTC';
                timezone
    -------------------------------
      2005-04-22 16:26:57.209082+09
    (1 row)
    
    test=# set time zone 'UTC';
    SET
    test=# select (current_timestamp at time zone 'UTC') at time zone 'UTC';
                timezone
    -------------------------------
      2005-04-22 07:27:55.841596+00
    (1 row)
    
    test=# select (current_timestamp at time zone 'UTC');
               timezone
    ----------------------------
      2005-04-22 07:28:48.888154
    (1 row)
    
    test=# select (current_timestamp at time zone 'UTC')::timestamptz;
                timezone
    -------------------------------
      2005-04-22 07:38:19.979511+00
    (1 row)
    

    【讨论】:

    • 或使用sql lang insted of plpgsqlselect ret from (select set_config('timezone', tzone, true), to_char(tstamp, mask) ret) t;pastebin.com/EC9KPfZ7
    【解决方案6】:

    简单/琐碎:

    SELECT REPLACE(NOW()::TEXT, ' ', 'T');
    

    或者如果需要更喜欢的人使用

    REGEXP_REPLACE()
    

    【讨论】:

      猜你喜欢
      • 2011-05-26
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      • 2017-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多