将时间戳从一个时区转换为另一个时区

时间:2015-03-20 09:53:30

标签: sql oracle11g toad

    A Table named TRADES has the following structure and Data:

    CREATE TABLE trades (
        trade_id                NUMBER,
        trade_execution_tmstmp  TIMESTAMP(6),
        time_zone_name          VARCHAR2 (30 BYTE),
        last_trade_marker       TIMESTAMP(6)
);

enter image description here

trade_id -- Unique ID for every trade

trade_execution_tmstmp - 交易在EST执行的时间 time_zone_name - 交易的本地时区 last_trade_marker - 特定日期最后一笔交易的EST时间

要求如下: 我必须开发一个程序,将次日交易插入另一个表next_day_trades。

如果程序在1月2日运行(在这种情况下),那么第二天只有1次交易,交易次数为4.因此,next_day_trades表将有1条记录。

决定次日交易的逻辑如下: trade_execution_tmstmp在EST中。它必须转换为本地时间戳,以查看交易何时在当地市场实际执行。在这种情况下,澳大利亚/悉尼 适用于所有行业。 last_trade_marker是该市场最后一次交易的时间。

下面是对表中第3和第4条记录的解释。

交易3在'1/2/2015 1:00:00.000000 PM'(EST)执行。 相当于澳大利亚/悉尼时间将是'2015年1月3日4:00:00.000000 AM' 1月2日的最后一个交易标记是'2015年1月3日2:00:00.000000 AM' 如果交易在12:00 - 02:00 AM(最后交易标记)之间执行,那将是次日交易。 因此,交易3不是第二天的交易。

交易4于'1/2/2015 10:00:00.000000 AM'(美国东部时间)执行。 相当于澳大利亚/悉尼时间将是'2015年1月3日1:00:00.000000 AM' 1月2日的最后一个交易标记是'2015年1月3日2:00:00.000000 AM' 如果交易在12:00 - 02:00 AM(最后交易标记)之间执行,那将是次日交易。 因此,交易4是次日交易。

注意:必须仅为存储过程执行日包含次日交易。这就是为什么,只有交易4插入next_day_trades表而不交易2,如果Proc在1月2日运行。

请帮我提出插入的SELECT查询。

1 个答案:

答案 0 :(得分:2)

您可以分两步将您的EST时间转换为声明的时区;首先通过from_tz()声明原始值所在的时区,然后使用at time zone转换运算符。

您需要将最后一个交易标记转换为带时区的时间戳,并且因为您还需要捕获当天的开始(对于00:00-02:00范围),您需要截断 - 将它作为日期 - 在将from_tz()应用于该日期之前。

select trade_id, trade_execution_tmstmp, time_zone_name, last_trade_marker,
  from_tz(trade_execution_tmstmp, 'EST') at time zone time_zone_name
    as trade_execution_local_tmstmp,
  from_tz(cast(trunc(last_trade_marker) as timestamp), time_zone_name)
    as last_trade_marker_start,
  from_tz(last_trade_marker, time_zone_name) as last_trade_marker_end
from trades;

更改会话以稍微不同地格式化值:

alter session set NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
alter session set NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS TZR';

得到:

  TRADE_ID TRADE_EXECUTION_TMSTM TIME_ZONE_NAME   LAST_TRADE_MARKER     TRADE_EXECUTION_LOCAL_TMSTMP         LAST_TRADE_MARKER_START              LAST_TRADE_MARKER_END              
---------- --------------------- ---------------- --------------------- ------------------------------------ ------------------------------------ ------------------------------------
         1 2015-01-01 13:00:00   Australia/Sydney 2015-01-02 02:00:00   2015-01-02 05:00:00 AUSTRALIA/SYDNEY 2015-01-02 00:00:00 AUSTRALIA/SYDNEY 2015-01-02 02:00:00 AUSTRALIA/SYDNEY
         2 2015-01-01 10:00:00   Australia/Sydney 2015-01-02 02:00:00   2015-01-02 02:00:00 AUSTRALIA/SYDNEY 2015-01-02 00:00:00 AUSTRALIA/SYDNEY 2015-01-02 02:00:00 AUSTRALIA/SYDNEY
         3 2015-01-02 13:00:00   Australia/Sydney 2015-01-03 02:00:00   2015-01-03 05:00:00 AUSTRALIA/SYDNEY 2015-01-03 00:00:00 AUSTRALIA/SYDNEY 2015-01-03 02:00:00 AUSTRALIA/SYDNEY
         4 2015-01-02 10:00:00   Australia/Sydney 2015-01-03 02:00:00   2015-01-03 02:00:00 AUSTRALIA/SYDNEY 2015-01-03 00:00:00 AUSTRALIA/SYDNEY 2015-01-03 02:00:00 AUSTRALIA/SYDNEY

根据我理解的规则,您可以比较这些调整后的列值,以确定它是否应该是次日交易:

select trade_id, trade_execution_tmstmp, time_zone_name, last_trade_marker,
  case when from_tz(trade_execution_tmstmp, 'EST') at time zone time_zone_name
     between from_tz(cast(trunc(last_trade_marker) as timestamp), time_zone_name)
       and from_tz(last_trade_marker, time_zone_name)
     then 'Yes' else 'No' end as next_day_trade
from trades;

  TRADE_ID TRADE_EXECUTION_TMSTM TIME_ZONE_NAME   LAST_TRADE_MARKER     NEXT_DAY_TRADE
---------- --------------------- ---------------- --------------------- --------------
         1 2015-01-01 13:00:00   Australia/Sydney 2015-01-02 02:00:00   No            
         2 2015-01-01 10:00:00   Australia/Sydney 2015-01-02 02:00:00   Yes           
         3 2015-01-02 13:00:00   Australia/Sydney 2015-01-03 02:00:00   No            
         4 2015-01-02 10:00:00   Australia/Sydney 2015-01-03 02:00:00   Yes           

'之间'可能不是这里的正确选择;取决于正好在02:00:00.0的交易是否计入第二天。您可能需要等效的

trade_execution_local_tmstmp >= last_trade_marker_start
and trade_execution_local_tmstmp < last_trade_marker_end

无论哪种方式,您都可以使用相同的条件来决定将哪些行复制到单独的表中。