Oracle 数据库中的 时间 时区-阿里云开发者社区

开发者社区> 长烟慢慢> 正文

Oracle 数据库中的 时间 时区

简介: 本节,我会引入很多概念,慢慢的一个一个的消化。。。。。。。 UTC是协调世界时(Universal Time Coordinated)英文缩写:协调世界时(英:Coordinated Universal Time,法:Temps Universel Coordonné),又称世界统一时间,世界标准时间,国际协调时间。
+关注继续查看

本节,我会引入很多概念,慢慢的一个一个的消化。。。。。。。

UTC是协调世界时(Universal Time Coordinated)英文缩写:协调世界时(英:Coordinated Universal Time,法:Temps Universel Coordonné),又称世界统一时间,世界标准时间,国际协调时间。英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。是由国际无线电咨询委员会规定和推荐,并由国际时间局(BIH)负责保持的以秒为基础的时间标度。UTC相当于本初子午线(即经度0度)上的平均太阳时,过去曾用格林威治平均时(GMT)来表示.北京时间比UTC时间早8小时,以1999年1月1日0000UTC为例,UTC时间是零点,北京时间为1999年1月1日早上8点整。

GMT(Greenwich Mean Time)是格林尼治平时:
由于地球轨道并非圆形,其运行速度又随着地球与太阳的距离改变而出现变化,因此视太阳时欠缺均匀性。视太阳日的长度同时亦受到地球自转轴相对轨道面的倾斜度所影响。为着要纠正上述的不均匀性,天文学家计算地球非圆形轨迹与极轴倾斜对视太阳时的效应。平太阳时就是指经修订后的视太阳时。在格林尼治子午线上的平太阳时称为世界时(UT0),又叫格林尼治平时(GMT)。参考http://zh.wikipedia.org/zhhans/%E4%B8%96%E7%95%8C%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4

为了确保协调世界时与世界时(UT1)相差不会超过0.9秒,有需要时便会在协调世界时内加上正或负闰秒。因此协调世界时与国际原子时(TAI)之间会出现若干整数秒的差别。位于巴黎的国际地球自转事务中央局(IERS)负责决定何时加入闰秒。

CET
欧洲中部时间(英語:Central European Time,CET)是比世界标准时间(UTC)早一个小时的时区名称之一。它被大部分欧洲国家和部分北非国家采用。冬季时间为UTC+1,夏季欧洲夏令时为UTC+2。
参考:http://zh.wikipedia.org/zh/%E6%AC%A7%E6%B4%B2%E4%B8%AD%E9%83%A8%E6%97%B6%E9%97%B4

CST
北京时间,China Standard Time,又名中国标准时间,是中国的标准时间。在时区划分上,属东八区,比协调世界时早8小时,记为UTC+8,与中华民国国家标准时间(旧称“中原标准时间”)、香港时间和澳门时间和相同。當格林威治時間為凌晨0:00時,中國標準時間剛好為上午8:00。
参考:http://zh.wikipedia.org/zh/CSThttp://zh.wikipedia.org/wiki/%E5%8C%97%E4%BA%AC%E6%97%B6%E9%97%B4

关系
CET=UTC/GMT + 1小时
CST=UTC/GMT +8 小时
CST=CET+9

DST夏令时:

DST是Daylight Saving Time的缩写,称为阳光节约时,在我国称为夏时制,又称夏令时,是一种为节约能源而人为调整地方时间的制度。有些国家DST的使用时间较长,(如美国长达7个月)跨越了春夏秋等三个季节,因此简单地用夏时制的概念已经不能完全表达DST的确切含义了,所以有人也称其为节能时。本文统一使用“DST”这一说法。所谓的DST,就是利用夏季天亮得早这一自然现象,人为地将时间提前一小时。这样就可以使人们早起早睡,以充分利用光照资源,减少照明时间,从而节约照明用电。


timezone offset 和 named timezone:

所谓offset就是指偏移,位移,比如我们东八区就会用 UTD/GMT +8 这个偏移量来表示;而named表示方法一般是这样:(example: Canada/Eastern ,Asia/Shanghai or GMT) ,直接用地区来表示这个timezone。那么既然有了这种offset的表示方法,何必再有用named的表示方法呢?原因就是因为上文提到的DST夏令时,有些非常注重环保节约的国家,会在夏季统一把时钟调快一个小时,比如伦敦冬天时UTC/GMT+0,但是到了夏天就成了UTC/GMT+1了。这样,偏移量表示就没法了,到底用哪个还得根据不同季节来回变,但是这个named timezone就好啦,不管怎么样,我就是伦敦timezone。


DATABASE timezone:参考文档:Timestamps & time zones - Frequently Asked Questions (文档 ID 340512.1)

数据库的时区并不像听起来那么重要。首先,它不影响像SYSDATE,或SYSTIMESTAMP功能,这些功能把他们的内容(日期和时间,并在SYSTIMESTAMP也时区的情况下)完全取决于操作系统。没有任何“oracle”产品的影响。

数据库时区的唯一功能是:它作为一个时区标准,“TIMESTAMP WITH LOCAL TIME ZONE”(TSLTZ)数据类型的值都被格式化并存储成当前数据库时区的格式。然而,在回话的检索或者插入式,这些存储的值将被转换成当前会话端的时区,所以数据库时区的实际设置是或多或少的不重要。
用于会话的时区是会话的时区,并在客户端的定义,而不是数据库端

该DBTIMEZONE应设置为一个偏移量(+00:00,-05:00或+09:00例如),或不会受DST(如UTC或GMT)静态时区,而不是一个命名时区是由DST(像欧洲/布鲁塞尔或美国/中部)的影响。

如何查看数据库当前的timezone呢?可以用如下命令:

select dbtimezone from dual;

这个dbtimezone只是用来格式化TSLTZ的数据,没有任何别的用处,会在数据库创建的时候有个sql( CREATE DATABASE... SET TIME_ZONE='+00:00';)可以去指定,如果不指定,就会用os server上的timezone offset。


After database creation the ALTER DATABASE SET TIME_ZONE statement can be used to change the database time zone. This will only work if there are no TSLTZ values already stored in the database or an  ORA-02231 (9i) or ORA-30079 will be seen:

SQL> ALTER DATABASE SET TIME_ZONE = '+00:00';

The change will not take effect until the database is restarted.


Why do I get ORA-02231 (9i) or ORA-30079 ( 10g and up) when I try to change the database time zone?

You can only change the database time zone if you have no TIMESTAMP WITH LOCAL TIME ZONE columns in the database otherwise ORA-02231: missing or invalid option to ALTER DATABASE (in 9i) or ORA-30079: cannot alter database timezone when database has TIMESTAMP WITH LOCAL TIME ZONE columns (in 10g and up) will be seen.  
To change the DBTIMEZONE for an database that has already TIMESTAMP WITH LOCAL TIME ZONE columns one need to
a) export all tables that have TIMESTAMP WITH LOCAL TIME ZONE columns

select c.owner || '.' || c.table_name || '(' || c.column_name || ') -' || c.data_type || ' ' col
from dba_tab_cols c, dba_objects o
where c.data_type like '%WITH LOCAL TIME ZONE'
and c.owner=o.owner
and c.table_name = o.object_name
and o.object_type = 'TABLE'
order by col
/

b) truncate or drop those tables
c) change the DBTIMEZONE making sure the are no tables with TSLTZ in the RECYCLEBIN and restart the database

SQL>PURGE DBA_RECYCLEBIN
/
SQL> ALTER DATABASE SET TIME_ZONE = '+00:00';
SQL> SHUTDOWN

 d) import the exported table again.


What is the difference between CURRENT_DATE, LOCALTIMESTAMP and CURRENT_TIMESTAMP?

They all depend on the session timezone, which is defined on the CLIENT side, not server side.

CURRENT_DATE returns the current date and time in the session time zone in a value of datatype DATE. 
LOCALTIMESTAMP returns the current date and time in the session time zone in a value of datatype TIMESTAMP. 
CURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE.

The sessions NLS_DATE_FORMAT defines the output format of a DATE, NLS_TIMESTAMP_FORMAT defines the output format of a TIMESTAMP, the NLS_TIMESTAMP_TZ_FORMAT defines the output format of a TIMESTAMP WITH TIME ZONE.

ALTER SESSION SET TIME_ZONE = '-05:00';
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT ='DD/MM/YYYY HH24:MI:SS TZR TZD' NLS_TIMESTAMP_FORMAT ='DD*MM*YYYY HH24:MI:SS' NLS_DATE_FORMAT ='DD-MM-YYYY HH24:MI:SS';
SELECT SESSIONTIMEZONE, CURRENT_DATE, CURRENT_TIMESTAMP, LOCALTIMESTAMP FROM DUAL;

-- gives for example:

SQL> SELECT SESSIONTIMEZONE, CURRENT_DATE, CURRENT_TIMESTAMP, LOCALTIMESTAMP FRO
M DUAL;
SESSIONTIMEZONE
---------------------------------------------------------------------------
CURRENT_DATE
-------------------
CURRENT_TIMESTAMP
---------------------------------------------------------------------------
LOCALTIMESTAMP
---------------------------------------------------------------------------
-05:00
28-10-2009 06:47:19
28/10/2009 06:47:18 -05:00
28*10*2009 06:47:18

-- and when doing an alter of the session timezone

ALTER SESSION SET TIME_ZONE = '-08:00';

-- gives for example:

SQL> SELECT SESSIONTIMEZONE, CURRENT_DATE, CURRENT_TIMESTAMP, LOCALTIMESTAMP FRO
M DUAL;
SESSIONTIMEZONE
---------------------------------------------------------------------------
CURRENT_DATE
-------------------
CURRENT_TIMESTAMP
---------------------------------------------------------------------------
LOCALTIMESTAMP
---------------------------------------------------------------------------
-08:00
28-10-2009 03:47:49
28/10/2009 03:47:49 -08:00
28*10*2009 03:47:49

more sample output is found in note 1624595.1 Clarification CURRENT_DATE, CURRENT_TIMESTAMP, LOCALTIMESTAMP ,SYSDATE, SYSTIMESTAMP, FIXED_DATE





2、概述

商业和数据库很多时候必须跨时区工作,从9i开始,oracle环境开始有了时区意识,通过指定数据库的时区和使用如下两种数据类型来存储时区:

TIMESTAMP WITH TIME ZONE和TIMESTAMP WITH LOCAL TIME ZONE。

 

TIMESTAMP WITH TIME ZONE(TSTZ):,存储了时间和真实的时区(用offset/name的形式表示),存储了现在的时间,时区是东八区。但是不会存储数据库的时区。这个数据类型的格式是由数据库参数NLS_TIMESTAMP_TZ_FORMAT来决定的,如下:

nls_timestamp_tz_format     string DD-MON-RR HH.MI.SSXFF AM TZR

当涉及到时区的时候,TSTZ通常是最好的存储时区信息的数据类型。通过下面这个查询,会查出你数据库中所有TSTZ的列:

select c.owner || '.' || c.table_name || '(' || c.column_name || ') -'
    || c.data_type || ' ' col
  from dba_tab_cols c, dba_objects o
 where c.data_type like '%WITH TIME ZONE'
    and c.owner=o.owner
   and c.table_name = o.object_name
   and o.object_type = 'TABLE'
order by col
/

TIMESTAMP WITH LOCAL TIME ZONE(TSLTZ):会同时存储数据库时区,并且会根据查询客户端的时区进行相应的转换。

 

数据库时区可以在创建时在create database命令中设置,也可以使用alter database set TIME_ZONE=...来修改。如果没有特别的指定,默认的,数据库将遵从主机操作系统时区设置,或者取自环境变量ORA_STDZ。所有支持的时区记录在V$TIMEZONE_NAMES动态性能表中。时区有三种表示方法,全名、缩写和相对于标准时间(格林威治时间)的固定偏移,比如标准时间相应的三种表示方法分别为:Etc/Greenwich、GMT和+00:00。

select c.owner || '.' || c.table_name || '(' || c.column_name || ') -'   || c.data_type || ' ' col
  from dba_tab_cols c, dba_objects o
 where c.data_type like '%WITH LOCAL TIME ZONE'
    and c.owner=o.owner
   and c.table_name = o.object_name
   and o.object_type = 'TABLE'
order by col
/





Oracle 9i 开始多了 3 个关于时间的数据类型:TIMESTAMP [(precision)] TIMESTAMP [(precision)] WITH TIME ZONE TIMESTAMP [(precision)] WITH LOCAL TIME ZONE,其中 TIMESTAMP [(precision)] WITH TIME ZONE 保存了时区信息。























版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Oracle11g--解决临时表空间过大问题
背景:         线上的生产数据库的临时表空间增长到了32GB,增长至最高上限,为了保证数据库的正常运行,有两套临时思路可供选项。         1)增加临时表空间的大小。
1116 0
获取数据库服务器日期、时间
一、获取数据库服务器日期(格式:yyyymmdd) sql server版本 string vsSql = "select convert(varchar(10),getdate(),112) as snTime"; oracle 版本 string vsSql = "select to_char(sysdate,'yyyymmdd') as snDate from d
1438 0
数据库5.7 日期有时间类型
简介 日期与时间类型 mysql中有多种表示日期的数据类型,主要有:DATETIME DATE TIMESTAMP,DATE .每一个类型都有合法的取值范围,当指定确实不合法的值时系统将“零”值插入到数据库中。
585 0
+关注
长烟慢慢
系统架构师
814
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载