【问题标题】:How can I convert "21-05-26 12:26:00.824000000 AMERICA/TORONTO" into format "2021-05-26T12:26:00.824Z"?如何将“21-05-26 12:26:00.824000000 AMERICA/TORONTO”转换为“2021-05-26T12:26:00.824Z”格式?
【发布时间】:2021-05-31 22:10:32
【问题描述】:

我试过这样,但它不起作用。

with
  inputs (ts) as (
    select '21-05-26 12:26:00.824000000 AMERICA/TORONTO' from dual 
  )
select to_timestamp_tz(ts,
                       'Dy Mon dd hh24:mi:ss TZD yyyy TZR',
                       'nls_date_language = english') as ts
from   inputs
;

【问题讨论】:

  • 您的格式与您输入的字符串值不匹配。但除此之外,如果输入代表多伦多当地时间 12:26。你真的想要(字符串)输出为 12:26 UTC 吗?还是您想要与多伦多时间等效的 UTC?

标签: sql oracle datetime


【解决方案1】:

您可以将输入字符串转换为带有时区值的时间戳:

select to_timestamp_tz(ts, 'RR-MM-DD HH24:MI:SS.FF TZR') as ts from inputs

由于您的输入字符串只有两位数字,您可以使用YY or RR;后者往往是合适的,但这取决于您的数据。理想情况下,您将有 4 位数的年份来避免该问题。您无需在此处指定语言,因为您没有任何日期或月份名称;它不疼,但什么也没做。时区名称不依赖于 NLS。

然后,您的客户端或应用程序将格式化显示,通常使用会话 NLS_TIMESTAMP_TZ_FORMAT 设置。如果您想要特定格式的字符串结果,您可以使用以下命令显式转换回字符串:

select to_char(
  to_timestamp_tz(ts, 'RR-MM-DD HH24:MI:SS.FF TZR'),
  'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"') as ts
from inputs ;

2021-05-26T12:26:00.824Z

"T""Z" 部分是 character literals

但是,'Z' 表示 UTC 时间,所以也许您应该使用 at UTC 将多伦多时间转换为 UTC:

select to_char(
  to_timestamp_tz(ts, 'RR-MM-DD HH24:MI:SS.FF TZR') at time zone 'UTC',
  'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"') as ts
from inputs ;

2021-05-26T16:26:00.824Z

db<>fiddle

但你应该只转换为字符串来显示;如果您要存储该值,则应将其保留为适当的时间戳、带时区的时间戳或带本地时区的时间戳。

【讨论】:

    【解决方案2】:

    我不确定您到底想要什么:您的主题标题说的是转换为格式化字符串,但在主题的正文中您询问的是转换为时间戳... 所以我两个都展示了:

    with inputs (ts) as ( select '21-05-26 12:26:00.824000000 AMERICA/TORONTO' from dual ) 
    select 
      v.*,
      to_char((string_to_timestamp at time zone 'UTC'),'yyyy-mm-dd"T"hh24:mi:ssxff3"Z"') timestamp_to_char_UTC
    from (
    select 
      ts, -- < string
      to_timestamp_tz(ts, 'yy-mm-dd hh24:mi:ssxff TZR', 'nls_date_language = english') as string_to_timestamp
    from inputs 
    ) v;
    
    TS                                          STRING_TO_TIMESTAMP                            TIMESTAMP_TO_CHAR_UTC
    ------------------------------------------- ---------------------------------------------- -------------------------
    21-05-26 12:26:00.824000000 AMERICA/TORONTO 2021-05-26 12:26:00.824000000 AMERICA/TORONTO  2021-05-26T16:26:00.824Z
    

    【讨论】:

    • 忽略时区 AMERICA/TORONTO 并仅添加 Z(表示 UTC 时间)会返回错误的时间。 12:26:00 AMERICA/TORONTO 不是 12:26:00 UTC
    • @WernfriedDomscheit 啊,不知道 Z 是时区同义词(它是 /usr/share/zoneinfo 中的 Zulu,而不是 Z),但 oracle 甚至不知道 Zulu,只是 UTC 或0..
    • 修复了查询
    • @SayanMalakshinov - 请求的输出格式为 ISO-8601,which uses Z to designate UTC。这不是甲骨文的事情。
    • @AlexPoole 我知道,但 TZR 也不是 Oracle 的东西......他们使用官方时区名称和区域,但不幸的是,oracle 不使用操作系统的时区文件,而是使用自己的带有时区的 TZ 文件每次需要升级的数据(V$TIMEZONE_FILE)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    相关资源
    最近更新 更多