将postgres日期表示转换为ISO 8601字符串

Cal*_*orm 29 postgresql date iso8601 elixir ecto

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

我的疑问是

SELECT
  now()::timestamp
Run Code Online (Sandbox Code Playgroud)

返回

[{{2016, 8, 9}, {3, 56, 55, 754181}}]
Run Code Online (Sandbox Code Playgroud)

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

我需要对查询进行哪些更改才能实现此目的?谢谢你的帮助.

Cal*_*orm 27

我想我找到了一种格式化的方法,但它并不理想,因为我自己编写格式.

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

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

  • 在我的情况下,我也需要几毫秒,所以你只需要在秒后添加.MS.`to_char(now():: timestamp at time zone'UTC','YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')` (4认同)
  • 这种形式不起作用,至少在 PG10 中是这样。::timestamp 删除 timezoneinformation 并且 'at timezone UTC' 再次移动偏移量,因此您将其移动两次。(now() 在时区 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"'); 确实有效 (2认同)
  • 为了让它工作,我需要将 `now()` 转换为 `timestamptz` 而不是 `timestamp`。 (2认同)
  • 这个答案是错误且危险的。仅当您的时区已经是 UTC 时,此方法才有效。将 timestamptz 转换为 timestamp 会导致时区偏移量被删除。然后 `at time zone` 将 zimezone 偏移量设置为 0。您不会将 timestamptz 转换为 UTC。相反,您只需覆盖时区偏移即可。`选择 now(), now() 在时区 'UTC', now()::timestamp 在时区 'UTC';` 2022-07-06 10:26:11.282728-05 | 2022-07-06 15:26:11.282728(正确的 UTC)| 2022-07-06 05:26:11.282728-05(不正确) (2认同)
  • @Mike你似乎是对的。我从未注意到任何这些时区转换困难,因为我将系统时间保持为 UTC,并且我总是为用户提供 UTC 并让他们自行转换。当您的系统时间不是 UTC 时,就会出现问题。如果其他人尝试过此操作,请首先使用“SET TIME ZONE 'America/Toronto';”(或任何其他非 UTC 区域),否则您可能看不到效果。将其设置为 UTC 以查看 UTC 到 UTC 的转换不执行任何操作。 (2认同)

Dat*_*aya 19

也许对某人而言,知道由于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
Run Code Online (Sandbox Code Playgroud)

  • 在Postgres 9.3中,to_json(now())中没有T。 (2认同)

adj*_*nks 7

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

SELECT to_json(now())#>>'{}'
Run Code Online (Sandbox Code Playgroud)

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

运算符“在指定路径上以文本形式获取[s] JSON对象”。但是,当您指定一个空数组文字'{}'作为路径时,它将指定根对象。

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

SELECT to_json(now())#>>'{}'
Run Code Online (Sandbox Code Playgroud)

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

*此外,JavaScript不会通过Date()构造函数解析第一种方法的输出,因为它希望简化ISO 8601该ISO 8601仅接受(+/-)HH:mmZ格式的时区,但F返回(+/-)HH格式无分钟。


rof*_*rol 5

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

要使用默认值 timezone 和 zone:

create table somedata (
  release_date timestamptz DEFAULT NOW()
)
Run Code Online (Sandbox Code Playgroud)

创建函数

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;
Run Code Online (Sandbox Code Playgroud)

并输出:

# 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)
Run Code Online (Sandbox Code Playgroud)

也看看这个

如果您希望服务器返回另一个时区各自的时区信息,我相信您需要使用 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)
Run Code Online (Sandbox Code Playgroud)


Hug*_*ugh 5

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. */
Run Code Online (Sandbox Code Playgroud)

这篇博文给出了相当详细的解释。