【问题标题】:Presto: Cast timestamp w/TZ to plain timestamp WITHOUT converting to UTCPresto:将带有 TZ 的时间戳转换为普通时间戳而不转换为 UTC
【发布时间】:2018-07-15 23:28:18
【问题描述】:

Presto 中的这个查询:

select *, 
  cast(ts_w_tz as timestamp) as ts, 
  cast(substr(cast(ts_w_tz as varchar), 1, 23) as timestamp) as local_ts_workaround 
from (select timestamp '2018-02-06 23:00:00.000 Australia/Melbourne' as ts_w_tz);

返回:

                   ts_w_tz                   |           ts            |   local_ts_workaround   
---------------------------------------------+-------------------------+-------------------------
 2018-02-06 23:00:00.000 Australia/Melbourne | 2018-02-06 12:00:00.000 | 2018-02-06 23:00:00.000

如您所见,将带时区的时间戳转换为时间戳的行为导致时间戳被转换回 UTC 时间(例如ts)。根据local_ts_workaround,IMO 正确的行为应该是返回时间戳的“墙上读数”。

我意识到有很多关于 Presto 对此的处理是错误的并且不符合 SQL 标准的帖子,并且正在修复中。但与此同时,这是一个很大的痛苦,因为似乎没有内置方法可以在没有时区的情况下获得本地化时间戳(根据local_ts_workaround)。

显然,我现在有字符串转换的解决方法,但这看起来很可怕。我想知道是否有人有更好的解决方法或者可以指出我遗漏的东西?

谢谢。

【问题讨论】:

  • 问题跟踪此错误:github.com/prestodb/presto/issues/7122(时间戳 W/TZ 转换回任何会话区域,不一定是 UTC)。您的解决方法很有效,但 format_datetime + parse_datetime 的组合可能更“明显正确”。

标签: sql presto


【解决方案1】:

似乎没有很好的解决方案,但基于之前的答案,我更喜欢这个……请参阅date_format_workaround 专栏:

select *,
  cast(from_iso8601_timestamp(date_format(ts_w_tz, '%Y-%m-%dT%H:%i:%s')) as timestamp) as date_format_workaround,
  cast(ts_w_tz as timestamp) as ts,
  cast(substr(cast(ts_w_tz as varchar), 1, 23) as timestamp) as local_ts_workaround
from (select timestamp '2018-02-06 23:00:00.000 Australia/Melbourne' as ts_w_tz);

【讨论】:

  • 虽然它本质上仍然是通过字符串转换并且并不理想,但我同意它比我自己的解决方法更强大。
【解决方案2】:
select cast(from_iso8601_timestamp('2018-02-06T23:00:00.000Z') as timestamp)

【讨论】:

  • 感谢您的回答,但这个问题专门针对您已经拥有带有时区类型的时间戳的情况。
猜你喜欢
  • 1970-01-01
  • 2019-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多