您误解了数据类型。正如您所指出的那样,时间戳不会存储时区,但而不是可让您“将时间节省到具有附加区域的数据库”。
当你这样做:
insert into toast values (TIMESTAMP '2019-09-23 16:03:11 US/Eastern');
你正在做文字值的隐式转换到纯时间戳,因为如果这样做:
insert into toast values (cast (TIMESTAMP '2019-09-23 16:03:11 US/Eastern' as timestamp));
原区信息不被保留或可用。没有转换(到UTC或其他任何东西),原始时区信息被丢弃。
select TIMESTAMP '2019-09-23 16:03:11 US/Eastern',
cast (TIMESTAMP '2019-09-23 16:03:11 US/Eastern' as timestamp)
from dual;
TIMESTAMP'2019-09-2316:03:11US/EASTERN' CAST(TIMESTAMP'2019-09-2316:
--------------------------------------- ----------------------------
23-SEP-19 16.03.11.000000000 US/EASTERN 23-SEP-19 16.03.11.000000000
来自timestamp文字的原始值显示时区;演员值没有时区信息。
如您所见,更改会话时区对纯timestamp
没有影响,因为没有时区信息可以产生任何效果。您将不得不使数据类型timestamp with time zone
或timestamp with local time zone
它有任何影响。
就你而言,由于你最终会处理不同时区的两个值,因此只有使用会话时区才能真正帮助你。你可以存储时区感知时间出发/到达机场:
create table toast (depart timestamp with time zone,
arrive timestamp with time zone);
insert into toast (depart, arrive)
values (TIMESTAMP '2019-09-23 08:00:00 US/Central',
TIMESTAMP '2019-09-23 11:00:00 US/Eastern');
alter session set time_zone = 'UTC';
Session altered.
select to_char(depart, 'HH24:MI TZR') as depart,
to_char(arrive, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
08:00 US/CENTRAL 11:00 US/EASTERN
,然后调整到当地机场/显示时间区域with datetime expressions,无论是明确将其命名为区域:
select to_char(depart at time zone 'US/Central', 'HH24:MI TZR') as depart,
to_char(arrive at time zone 'US/Central', 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
08:00 US/CENTRAL 10:00 US/CENTRAL
select to_char(depart at time zone 'US/Eastern', 'HH24:MI TZR') as depart,
to_char(arrive at time zone 'US/Eastern', 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
09:00 US/EASTERN 11:00 US/EASTERN
或通过,如果你有信心在本地会话时区是正确的:
alter session set time_zone = 'US/Central';
select to_char(depart at local, 'HH24:MI TZR') as depart,
to_char(arrive at local, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
08:00 US/CENTRAL 10:00 US/CENTRAL
alter session set time_zone = 'US/Eastern';
select to_char(depart at local, 'HH24:MI TZR') as depart,
to_char(arrive at local, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
09:00 US/EASTERN 11:00 US/EASTERN
这可能是更好的存储倍UTC,虽然,这可以在普拉伊完成ñ时间戳仍,如果你喜欢 - 所以一切都假定存储的数值总是UTC - 和你原来的时间转换为UTC,手动或sys_extract_utc()
:
create table toast (depart timestamp, arrive timestamp);
insert into toast (depart, arrive)
values (sys_extract_utc (TIMESTAMP '2019-09-23 08:00:00 US/Central'),
sys_extract_utc (TIMESTAMP '2019-09-23 11:00:00 US/Eastern'));
...
alter session set time_zone = 'US/Eastern';
select to_char(from_tz(depart, 'UTC') at local, 'HH24:MI TZR') as depart,
to_char(from_tz (arrive, 'UTC') at local, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
09:00 US/EASTERN 11:00 US/EASTERN
但包括区域也许是更安全:
create table toast (depart timestamp with time zone,
arrive timestamp with time zone);
insert into toast (depart, arrive)
values (TIMESTAMP '2019-09-23 08:00:00 US/Central' at time zone 'UTC',
TIMESTAMP '2019-09-23 11:00:00 US/Eastern' at time zone 'UTC');
...
alter session set time_zone = 'US/Eastern';
select to_char(depart at local, 'HH24:MI TZR') as depart,
to_char(arrive at local, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
09:00 US/EASTERN 11:00 US/EASTERN
但是如果你使用timestamp with local time zone
你种得最好的两个,更简单地说,和你是如何转换的输入时间regarless:
create table toast (depart timestamp with local time zone,
arrive timestamp with local time zone);
insert into toast (depart, arrive)
values (TIMESTAMP '2019-09-23 08:00:00 US/Central',
TIMESTAMP '2019-09-23 11:00:00 US/Eastern' at time zone 'UTC');
alter session set time_zone = 'UTC';
select to_char(depart, 'HH24:MI TZR') as depart,
to_char(arrive, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
13:00 UTC 15:00 UTC
alter session set time_zone = 'US/Central';
select to_char(depart, 'HH24:MI TZR') as depart,
to_char(arrive, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
08:00 US/CENTRAL 10:00 US/CENTRAL
alter session set time_zone = 'US/Eastern';
select to_char(depart, 'HH24:MI TZR') as depart,
to_char(arrive, 'HH24:MI TZR') as arrive
from toast;
DEPART ARRIVE
-------------------------------------- --------------------------------------
09:00 US/EASTERN 11:00 US/EASTERN
(ALS o请阅读Tony’s Tirade against TIMESTAMP WITH TIME ZONE了解更多关于数据类型选项的背景信息。)
优秀答案 –
@Alex Poole非常感谢您的详细解答!我用以下问题更新了消息:我浏览了之前提到的那篇论文。我也看过其他文章。基本上,似乎是使用TIMESTAMP WITH LOCAL TIMEZONE(?)如果是这样,那么TIMESTAMP WITH TIMEZONE是否可以替代TIMESTAMP WITH LOCAL TIMEZONE? TIA –
@CaseyHarrils - 你一定已经在Tony的文章中对表格下的项目符号进行了非常不同的解释, “当您在不同时区周围复制数据时,请使用TIMESTAMP WITH LOCAL TIME ZONE”和“不要打扰TIMESTAMP或TIMESTAMP WITH TIME ZONE”。他们都有问题,但'当地时区的时间戳'似乎是最简单的(基地唐Tonay的工作)最适合你在做什么?如上所示,坚持使用'时间戳'并强制所有东西都可以工作,并且可能是航空的常用方法。 –