问题
I'm looking for a generic function that allows me to parse ISO8601 timestamps. I know about to_timestamp_tz but I couldn't find a way to create a format
parameter that will parse all the possible variations of ISO-8601 datetimes:
select '2012-01-01T12:00:00+00:00'::timestamp_tz; // this works
select '2012-01-01T12:00:00+0000'::timestamp_tz; //Timestamp '2012-01-01T12:00:00+0000' is not recognized, although is a valid iso8601 (no colon in the timezone)
select to_timestamp_tz('2012-01-01T12:00:00.123456+00:00', 'YYYY-MM-DDTHH24:MI:SS.FFTZH:TZM'); // works
select to_timestamp_tz('2012-01-01T12:00:00.123456+0000', 'YYYY-MM-DDTHH24:MI:SS.FFTZH:TZM'); // Can't parse '2012-01-01T12:00:00.123456+0000' as timestamp with format 'YYYY-MM-DDTHH24:MI:SS.FFTZH:TZM', again because of it has no colon in the timezone
select to_timestamp_tz('2012-01-01T12:00:00.123456+0000', 'YYYY-MM-DDTHH24:MI:SS.FFTZHTZM'); //works
select to_timestamp_tz('2012-01-01T12:00:00.123456+00:00', 'YYYY-MM-DDTHH24:MI:SS.FFTZHTZM'); //Can't parse '2012-01-01T12:00:00.123456+00:00' as timestamp with format 'YYYY-MM-DDTHH24:MI:SS.FFTZHTZM' , fails because it doesn't expect a colon in the timezone
So is there anyway to parse a generic ISO 8601? (My input can come with different variations of ISO 8601).
Examples input that it should parse:
2012-01-01T12:00:00.123456+00:00
2012-01-01T12:00:00.123456+0000
2012-01-01T12:00:00.123456+00
2012-01-01T12:00:00.123456Z
2012-01-01T12:00+00:00 // no seconds
2012-01-01T12:00+0000
2012-01-01T12:00+01
2012-01-01T12:00Z
Mostly is reduced to handle the 4 ways of expressing the UTC offset (+00:00
, +0000
, +00
and Z
) and having optional seconds and fractional seconds.
回答1:
You can set the Parameter TIMESTAMP_INPUT_FORMAT to AUTO
,
which means the following formats will be recognized:
Supported Formats for AUTO Detection/Timestamp Formats
If the main problem is colons, you can strip the colons from the input string before converting using a TIMESTAMP
format:
SELECT TO_TIMESTAMP_LTZ(
TRANSLATE('2019-11-25T14:16:36.556 +01:00', ':', ''),
'YYYY-MM-DD"T"HH24MISS.FF TZHTZM'
);
JavaScript seems to recognize more ISO variants than Snowflake SQL, but truncates to precision (3):
CREATE OR REPLACE FUNCTION CONV_TS(DT TEXT) RETURNS VARIANT LANGUAGE JAVASCRIPT STRICT
AS 'return new Date(DT).toJSON()';
SELECT TRY_TO_TIMESTAMP_TZ(TS) TRY_TZ, CONV_TS(TS)::TIMESTAMP_TZ JS_TS, TS FROM VALUES
('2012-01-01T12:00:00.123456+00:00'),
('2012-01-01T12:00:00.123456+0000'), // Also fails TRY%
('2012-01-01T12:00:00.123456+00'), // Fails JS
('2012-01-01T12:00:00.123456Z'),
('2012-01-01T12:00+00:00'),
('2012-01-01T12:00+0000'), // Also fails TRY%
('2012-01-01T12:00+01'), // Fails JS
('2012-01-01T12:00Z') v(ts);
=>
2012-01-01 12:00:00.123 +0000 2012-01-01 12:00:00.123 +0000 2012-01-01T12:00:00.123456+00:00
NULL 2012-01-01 12:00:00.123 +0000 2012-01-01T12:00:00.123456+0000
NULL NULL 2012-01-01T12:00:00.123456+00
2012-01-01 12:00:00.123 +0000 2012-01-01 12:00:00.123 +0000 2012-01-01T12:00:00.123456Z
2012-01-01 12:00:00.000 +0000 2012-01-01 12:00:00.000 +0000 2012-01-01T12:00+00:00
NULL 2012-01-01 12:00:00.000 +0000 2012-01-01T12:00+0000
NULL NULL 2012-01-01T12:00+01
2012-01-01 12:00:00.000 +0000 2012-01-01 12:00:00.000 +0000 2012-01-01T12:00Z
来源:https://stackoverflow.com/questions/59030297/how-can-i-parse-an-iso-8601-timestamp-with-snowflake-sql