我有一个数据库,它将日期存储为具有UTC偏移的日期时间。 如何将这些日期从UTC转换为在select语句中说出CET?
是否有某种语法糖可以照顾整个白天的秋/冬和春/夏偏移的东西?
修改: 我在CodePlex上发现了this库非常有用:
DateTimeUtil
用于扩展日期时间处理的一组UDF和配置数据,例如: G。它提供简单的时区转换,包括。使用本机T-SQL(无CLR)支持夏令时。
答案 0 :(得分:1)
SELECT CONVERT(VARCHAR, dbo.udfToLocalTime(t.CreatedDateTime, '1'), 113)
FROM yourtable t
如果有更新:
UPDATE yourtable t
SET t.CreatedDateTime = CONVERT(VARCHAR, dbo.udfToLocalTime(t.CreatedDateTime, '1'), 113)
使用如下的UDF
CREATE FUNCTION udfToLocalTime
(
@UtcDateTimeAS DATETIME
,@UtcOffset AS INT = -8 --PST
)
RETURNS DATETIME
AS
BEGIN
DECLARE @PstDateTimeAS DATETIME
,@Year AS CHAR(4)
,@DstStart AS DATETIME
,@DstEndAS DATETIME
,@Mar1 AS DATETIME
,@Nov1 AS DATETIME
,@MarTime AS TIME
,@NovTime AS TIME
,@Mar1Day AS INT
,@Nov1Day AS INT
,@MarDiff AS INT
,@NovDiff AS INT
SELECT @Year = YEAR(@UtcDateTime)
,@MarTime = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset, '1900-01-01 02:00'))
,@NovTime = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset - 1, '1900-01-01 02:00'))
,@Mar1 = CONVERT(CHAR(16), @Year + '-03-01 ' + CONVERT(CHAR(5), @MarTime), 126)
,@Nov1 = CONVERT(CHAR(16), @Year + '-11-01 ' + CONVERT(CHAR(5), @NovTime), 126)
,@Mar1Day = DATEPART(WEEKDAY, @Mar1)
,@Nov1Day = DATEPART(WEEKDAY, @Nov1)
--Get number of days between Mar 1 and DST start date
IF @Mar1Day = 1
SET @MarDiff = 7
ELSE
SET @MarDiff = 15 - @Mar1Day
--Get number of days between Nov 1 and DST end date
IF @Nov1Day = 1
SET @NovDiff = 0
ELSE
SET @NovDiff = 8 - @Nov1Day
--Get DST start and end dates
SELECT @DstStart = DATEADD(DAY, @MarDiff, @Mar1)
,@DstEnd= DATEADD(DAY, @NovDiff, @Nov1)
--Change UTC offset if @UtcDateTime is in DST Range
IF @UtcDateTime >= @DstStart AND @UtcDateTime < @DstEnd
SET @UtcOffset = @UtcOffset + 1
--Get Conversion
SET @PstDateTime = DATEADD(HOUR, @UtcOffset, @UtcDateTime)
RETURN @PstDateTime
END
答案 1 :(得分:0)
如果您的数据库包含UTC日期,那将是完美的。更好的方法是使用您的操作系统时区偏移量。
例如:
select
dateadd(minute,DATEPART(TZ, SYSDATETIMEOFFSET()), YourUTCDate) as timestamp
from YourTable
答案 2 :(得分:0)
使用以下函数转换日期时间区域。
create or replace FUNCTION timezoneConverter
(v_date in date, inputDateZone in varchar2 default 'UTC', outputDateZone in varchar2 default 'UTC')
return date AS date_out date;
BEGIN
SELECT
to_date(
to_char(FROM_TZ(to_timestamp(to_char( v_date,'dd.mm.yyyy hh24:mi:ss' ),'dd.mm.yyyy hh24:mi:ss'),
to_char(inputDateZone)) AT TIME ZONE
to_char(outputDateZone),
'dd.mm.yyyy hh24:mi:ss'), 'dd.mm.yyyy hh24:mi:ss')
into date_out FROM dual;
return date_out;
EXCEPTION
when others then
DBMS_OUTPUT.put_line('Date:' || v_date || 'TZ:' || inputDateZone || '-' || outputDateZone || ' / ' || sqlcode || ' / ' || SQLERRM(sqlcode));
--date_out := to_date(to_char(v_date-1/24, 'yyyymmddhh24miss'), 'yyyymmddhh24miss');
date_out := null;
return date_out;
END;
/
DayLight 中欧时间 (CET
) 与中欧夏令时间 (CEST
)
Short Hour 跳过第二个小时。 Note: hours shift because clocks change forward 1 hour.
--set serveroutput on; -- View -> Dbms Output : set serveroutput on [serveroutput must be set ON or OFF or OPTIMIZED or UNOPTIMIZED]
SELECT
timezoneConverter(to_timestamp('2020-03-29T01:00Z', 'yyyy-mm-dd"T"hh24:mi"Z"'), 'CET', 'UTC') CETtoUTC1, -- 29-MAR-2020 00:00:00
timezoneConverter(to_timestamp('2020-03-29T02:00Z', 'yyyy-mm-dd"T"hh24:mi"Z"'), 'CET', 'UTC') CETtoUTC2, -- (null)
timezoneConverter(to_timestamp('2020-03-29T02:00Z', 'yyyy-mm-dd"T"hh24:mi"Z"'), 'UTC', 'CET') UTCtoCET FROM dual; -- 29-MAR-2020 04:00:00
-- Date:29-MAR-2020 02:00:00TZ:CET-UTC / -1878 / ORA-01878: specified field not found in datetime or interval
Long Hour 第二个小时重复 Note: hours shift because clocks change backward 1 hour.
SELECT
timezoneConverter(to_timestamp('2020-10-25T02:00Z', 'yyyy-mm-dd"T"hh24:mi"Z"'), 'UTC', 'CET') UTCtoCET, -- 25-OCT-2020 03:00:00
timezoneConverter(to_timestamp('2020-10-25T02:00Z', 'yyyy-mm-dd"T"hh24:mi"Z"'), 'CET', 'UTC') CETtoUTC2, -- 25-OCT-2020 01:00:00
timezoneConverter(to_timestamp('2020-10-25T01:00Z', 'yyyy-mm-dd"T"hh24:mi"Z"'), 'CET', 'UTC') CETtoUTC1 FROM dual; -- 24-OCT-2020 23:00:00
以下示例将一个时区的日期时间值转换为另一个时区:docs.oracle.com
SELECT FROM_TZ(CAST(TO_DATE('1999-12-01 11:00:00',
'YYYY-MM-DD HH:MI:SS') AS TIMESTAMP), 'America/New_York')
AT TIME ZONE 'America/Los_Angeles' "West Coast Time"
FROM DUAL;
West Coast Time
------------------------------------------------
01-DEC-99 08.00.00.000000 AM AMERICA/LOS_ANGELES