【问题标题】:Oracle - Converting a UTC timestamp to a localtime (GMT/BST) timestampOracle - 将 UTC 时间戳转换为本地时间 (GMT/BST) 时间戳
【发布时间】:2018-09-17 08:37:18
【问题描述】:

我必须创建将日期时间作为 UTC 转换为本地时间 (GMT/BST)

数据库中的日期是 UTC 并且数据库设置为 UTC。

我相信我可以使用 TZ_OFFSET 获得 UTC 和(例如)BST 之间的偏移量,但是我如何使用它来将 UTC 日期时间转换为 BST 日期时间?

因此,例如,如果数据库 (UTC) 日期时间是

     '2018-04-03 14:30:00'

而偏移量是'+01:00'

我希望结果是

     '2018-04-03 15:30:00'

如果有一种优雅的方式来做到这一点?而不是使用蹩脚的算术(然后必须考虑午夜、月末、年末等)

谢谢

【问题讨论】:

    标签: oracle datetime utc


    【解决方案1】:

    使用FROM_TZ创建TIMSTAMP WITH TIME ZONE,那么转换就很简单了,例如:

    FROM_TZ({your column}, 'UTC') AT TIME ZONE 'Europe/London'
    

    【讨论】:

    • 谢谢。成功了!
    【解决方案2】:

    如您在文档中所见:

    Converting Time Zones With the AT TIME ZONE Clause 的示例:

    SELECT FROM_TZ(CAST(TO_DATE('1999-12-01 11:00:00',
         'YYYY-MM-DD HH:MI:SS') AS TIMESTAMP), 'America/New_York')
         AT TIME ZONE 'America/Los_Angeles' "West Coast Time"
    FROM DUAL;
    
    West Coast Time
    ----------------------------------------------------------
    01-DEC-99 08.00.00.000000 AM AMERICA/LOS_ANGELES
    

    因此,应用于您的案例场景:

    SELECT FROM_TZ(CAST(TO_DATE('2018-04-03 14:30:00',
         'YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP), 'UTC')
         AT TIME ZONE 'GMT' "Greenwich Mean Time"
    FROM DUAL;
    
    Greenwich Mean Time
    ----------------------------------------------------------
    03-APR-18 02.30.00.000000 PM GMT
    

    您可以通过以下方式获取可用时区列表:

    SELECT tzname, tzabbrev FROM V$TIMEZONE_NAMES;
    

    如果您有一个表 YOUR_TABLE 和一列 some_timestamp

    create table YOUR_TABLE (
        some_timestamp timestamp
    );
    /
    
    insert into YOUR_TABLE (
     SOME_TIMESTAMP
    ) values (
      CAST(TO_DATE('2018-04-03 14:30:00', 'YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP)
    );
    

    然后就可以运行了:

    select
      SOME_TIMESTAMP,
      FROM_TZ(SOME_TIMESTAMP, 'UTC') AT TIME ZONE 'GMT' "Greenwich Mean Time",
      FROM_TZ(SOME_TIMESTAMP, 'UTC') AT TIME ZONE 'Europe/London' "London Time"
    from YOUR_TABLE;
    
    SOME_TIMESTAMP                  Greenwich Mean Time              London Time
    ----------------------------------------------------------
    03-APR-18 02.30.00.000000 PM    03-APR-18 02.30.00.000000 PM GMT    03-APR-18 03.30.00.000000 PM EUROPE/LONDON
    

    如果您绝对确定您的服务器是 UTC 以及引入的时间戳,那么您可以跳过该 UTC 转换部分:

    select
      SOME_TIMESTAMP,
      SOME_TIMESTAMP AT TIME ZONE 'GMT' "Greenwich Mean Time",
      SOME_TIMESTAMP AT TIME ZONE 'Europe/London' "London Time"
    from YOUR_TABLE;
    

    【讨论】:

    • UTC与GMT基本一致,所以你的代码没用。
    • Wernfried Domscheit,我按照定义来回答这个问题。它对于 UTC -> GMT 是没用的,因为是同一件事,但这不是问题。但是,我使用伦敦时区(夏季从 GMT 更改为 BST)更新了响应以明确这一点。
    • SOME_TIMESTAMP AT TIME ZONE 'Europe/London' 不起作用,因为当您将 TIMESTAMPDATE 转换为 TIMESTAMP WITH TIME ZONE 时,Oracle 会采用当前的 SESSIONTIMEZONE(可以是任何值) - 而不是服务器时区.
    • Wernfried Domscheit,如果您阅读了这个问题,它会说:The dates in the database are UTC AND the database is set to UTC.。如果你看了我的回复,我说:if you are absolutely sure that your server is in UTC...
    • @WernfriedDomscheit:GMT 与 UTC 相同;前者是英国时区冬季部分的标识符,在夏季时间切换到 BST。 UTC 永远不会。
    【解决方案3】:

    应该很简单::

    select datetimecolumn + INTERVAL '1' HOUR from mytable
    

    希望我能正确理解您的要求。

    【讨论】:

    • 你如何处理夏令时?
    • 好问题,是的,我的解决方案不适合这个问题。
    • 谢谢。我相信 UTC/BST 的等价物是 SELECT FROM_TZ(CAST(TO_DATE('1999-12-01 11:00:00', 'YYYY-MM-DD HH:MI:SS') AS TIMESTAMP), 'UTC')在时区“欧洲/伦敦”“伦敦时间”来自 DUAL;但这将返回与 UTC 相同的时间。 (似乎没有考虑到 BST 的 +1 小时调整)
    • 是的,因为您使用的是冬季时间 12 月进行测试。在夏天尝试约会,然后您将获得补偿。
    猜你喜欢
    • 2019-08-15
    • 2019-03-09
    • 2019-01-05
    • 2013-03-23
    • 2015-04-20
    • 2011-02-06
    • 2012-03-20
    • 1970-01-01
    • 2017-06-10
    相关资源
    最近更新 更多