我想知道如何从时区偏移量中获取时区名称。例如,如果我有"GMT-07_(PDT)
我应该得到America/Los_Angeles
返回。同样,GMT+5.5_(INDIA)
应该返回Asia/Kolkata
和GMT+09_(JAPAN)
应该返回Asia/Tokyo
。
我必须在Oracle中实现这一点。
一些字符串操作和以下操作的组合应该让你接近
TZ_OFFSET()
,它根据时区区域名称返回偏移量V$TIMEZONE_NAMES
,具有时区区域和缩写首先,您需要提取提供的偏移量:
select regexp_replace( 'GMT+5.5_(INDIA)'
, '[[:alpha:]]{3}(-|\+)(\d+)(\.(\d+))?.*'
, '\1\2\3')
from dual
然后,您需要将其转换为正确的格式。假设正则表达式为您提供了一个名为s
的东西,那么:
with setup as (
select to_number(s) as n from ...
)
select case when n < 0 then '-' else '+' end
|| lpad(trunc(n), 2, '0')
|| ':'
|| lpad((n - trunc(n)) * 60, 2, '0') as offset
from dual
最后,您可以使用它来查询我们的视图,使用TZ_OFFSET
返回所有有效的时区区域。
select tzname
from v$timezone_names
where tzoffset(tzname) = :offset
如果要选择一个时区区域,则需要创建一些额外的逻辑来描述您要选择的区域。
在单个查询中,这看起来很难看,但就像是
with strip_characters as (
select to_number(regexp_replace( 'GMT+5.5_(INDIA)'
, '[[:alpha:]]{3}(-|\+)(\d+)(\.(\d+))?.*'
, '\1\2\3'))
from dual
)
, setup as (
select case when n < 0 then '-' else '+' end
|| lpad(trunc(n), 2, '0')
|| ':'
|| lpad((n - trunc(n)) * 60, 2, '0') as offset
from strip_characters
)
select t.tzname
from v$timezone_names t
join setup s
where tzoffset(t.tzname) = s.offset
所有案例都无法以可靠的方式提出要求。任何企图都会偏向特定的世界观。
例如,你给了GMT-07_(PDT)
并说它应该是America/Los_Angeles
。这意味着美国的时区标识符在某种程度上更为重要。所有以下规范区域标识符均使用Pacific Daylight Time和GMT-07:
America/Los_Angeles
(美国)America/Tijuana
(墨西哥)America/Vancouver
(加拿大)America/Dawson
(加拿大)America/Whitehorse
(加拿大)即使以美国为中心的世界观,并限制于现代,它仍然无效。考虑另一个例子:GMT-07_(MST)
。那是America/Denver
还是America/Phoenix
? Denver表示在夏令时间内在-7和-6之间转换的区域,但Phoenix表示在-7全年没有夏令时的区域。
这些是相对简单的例子。考虑一下你是否有GMT+01_(CET)
。与之抗衡的差异数量有很多要列出。
还要考虑并非每个时区都有一个有意义的缩写,并且时区缩写不一致(例如:HST与HAST)并且通常不明确(例如:CST)。
通常,可以从特定时间点的时区标识符确定偏移(有时是缩写),但是不能实现相反的方向。
另请参阅the timezone tag wiki中的“时区!=偏移”。