简体   繁体   English

Oracle SQL:将时间戳转换为UTC

[英]Oracle SQL: converting timestamp to UTC

I have a simple select query such as below but I noticed I am getting back the regional times. 我有一个简单的选择查询,如下所示,但我注意到我回到了区域时间。 How can I convert to UTC in my select statment? 如何在我选择的陈述中转换为UTC?

select myTimeStamp, MyName, MyBranch from tableA

Result: '27/03/2014 15:15:26' 'john', 'london' 结果:“ 27/03/2014 15:15:26”“约翰”,“伦敦”

I have tried using sys_extract_utc (myTimeStamp) but I have the error 我尝试使用sys_extract_utc(myTimeStamp),但出现错误

sql command not properly ended sql命令未正确结束

The column myTimestamp is of type 'date'. myTimestamp列的类型为“ date”。

select cast(mytimestamp as timestamp) at time zone 'UTC', 
       MyName, 
       MyBranch 
from tableA

Because mytimestamp is in fact a date not a timestamp you need to cast it. 因为mytimestamp实际上是date而不是时间戳,所以您需要转换它。 Doing that makes Oracle assume that the information stored in mytimestamp is in the time zone of the server -if that isn't the case you need to use Madhawas' solution. 这样做使Oracle假定存储在mytimestamp中的信息位于服务器的时区中-如果不是这种情况,则需要使用Madhawas的解决方案。

Depending on the type, there are a couple of gotchas with regard to what time zone Oracle is converting from depending on what the data type of myTimestamp is. 根据类型,根据myTimestamp的数据类型,Oracle从哪个时区转换有一些陷阱。

timestamp with time zone 带时区的时间戳

It Just Works™. It Just Works™。 a_horse_with_no_name has the right answer here. a_horse_with_no_name在这里有正确的答案。

timestamp with local time zone 带本地时区的时间戳

it is implicitly cast to timestamp with time zone , then It Just Works™. 它被隐式转换为带时区的时间戳 ,然后是Just Just™。 Again, a_horse_with_no_name is right here. 同样, a_horse_with_no_name就在这里。

timestamp 时间戳记

While it too is implicitly cast to timestamp with time zone , the time zone that gets assigned by default is the session time zone (as opposed to the database time zone). 尽管它也被隐式转换为带有时区的时间戳 ,但默认情况下分配的时区是会话时区(与数据库时区相反)。

  • The explicit invocation of this is myTimestamp at local . 对此的显式调用是myTimestamp at local
  • Alternatively (and most likely better), you can do as Madhawas says and use the from_tz function to explicitly build a value with an explicit time zone other than that of your session. 另外(可能更好),您可以按照Madhawas所说的做,并使用from_tz函数显式地建立一个具有与会话不同的显式时区的值。

date 日期

Trying to do any of the above to date will fail as you described: 到目前为止 ,尝试执行上述任何操作都会失败,如下所述:

  • myTimestamp at time zone 'UTC'
    ORA-30084: invalid data type for datetime primary with time zone modifier ORA-30084:具有时区修饰符的datetime主数据类型无效

  • from_tz(myTimestamp, 'America/New_York')
    ORA-00932: inconsistent datatypes: expected TIMESTAMP got DATE ORA-00932:数据类型不一致:预期的时间戳记是DATE

The solution here is to cast the date to a timestamp first: 这里的解决方案是首先将日期转换为时间戳

select from_tz(cast(myTimestamp as timestamp), 'America/New_York') from tableA

Sample Script 样例脚本

The following script illustrates the behavior. 以下脚本说明了该行为。 Note that on my system, dbtimezone is US/Central, and sessiontimezone is GMT-05:00. 请注意,在我的系统上, dbtimezone是美国/中央,而sessiontimezone是GMT-05:00。

I also use to_char to convert the output as I have found some tools will alter the result timestamp in subtle ways, particularly if they don't have good timestamp support (this is rare nowadays, but still potentially a problem). 我还使用to_char来转换输出,因为我发现某些工具会以微妙的方式更改结果时间戳,尤其是如果它们没有良好的时间戳支持(如今很少见,但仍然可能是一个问题)。

alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'
/
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'
/

select dbtimezone
      ,sessiontimezone
      ,to_char(timestamp '2017-01-01 06:00:00') as ts
      ,to_char(timestamp '2017-01-01 06:00:00' at local) as ts_at_local
      ,to_char(timestamp '2017-01-01 06:00:00' at time zone dbtimezone) as ts_at_db
      ,to_char(timestamp '2017-01-01 06:00:00' at time zone sessiontimezone) as ts_at_session
 from dual
/

The output on my system is as follows (reformatted as columnar for readability): 我的系统上的输出如下(为了便于阅读,将其重新格式化为列式):

DBTIMEZONE          US/Central
SESSIONTIMEZONE     -05:00
TS                  2017-01-01 06:00:00
TS_AT_LOCAL         2017-01-01 06:00:00 -05:00
TS_AT_DB            2017-01-01 05:00:00 US/CENTRAL
TS_AT_SESSION       2017-01-01 06:00:00 -05:00

您需要知道您的时区;

SELECT myTimeStamp, from_tz(myTimeStamp, 'America/New_York') AT TIME ZONE 'UTC' utc FROM dual;

Starting from Oracle 19c, a new function is introduced which is TO_UTC_TIMESTAMP_TZ 从Oracle 19c开始,引入了一个新函数TO_UTC_TIMESTAMP_TZ

The SQL function TO_UTC_TIMESTAMP_TZ takes an ISO 8601 date format string as the varchar input and returns an instance of SQL data type TIMESTAMP WITH TIMEZONE. SQL函数TO_UTC_TIMESTAMP_TZ将ISO 8601日期格式的字符串作为varchar输入,并返回SQL数据类型TIMESTAMP WITH TIMEZONE的实例。 It normalizes the input to UTC time (Coordinated Universal Time, formerly Greenwich Mean Time). 它将输入标准化为UTC时间(协调世界时,以前为格林威治标准时间)。 Unlike SQL function TO_TIMESTAMP_TZ , the new function assumes that the input string uses the ISO 8601 date format, defaulting the time zone to UTC 0. 与SQL函数TO_TIMESTAMP_TZ不同,新函数假定输入字符串使用ISO 8601日期格式,默认时区为UTC 0。

select TO_UTC_TIMESTAMP_TZ ( to_char(sysdate,'yyyy-mm-dd"T"HH:MI:SS') )  as utc 
   from dual;

 UTC
31-MAR-19 05.45.36.000000 AM +00:00

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM