带有JavaScript的Snowflake UDF返回错误的日期



我遇到了一个问题,在Snowflake中用JavaScript语言实现的用户定义函数(UDF(返回无效日期,它会增加一天。

为了证明这个问题,这里有一个简单的UDF,它包含三个参数year、month、day,并返回Date对象。

CREATE OR REPLACE FUNCTION JDC(YEAR FLOAT,MONTH FLOAT,DAY FLOAT)
RETURNS DATE
LANGUAGE JAVASCRIPT
AS
$$
// In Java Script months start with 0 so -1
return new Date(YEAR,MONTH-1,DAY)
$$
;

调用此过程将返回除1942年至1949年之间的几天之外的所有年份的正确值,

  1. select JDC(1942,02,10);返回1942-02-11,这是不正确的
  2. select JDC(1948,12,31);返回1949-01-01错误
  3. select JDC(2020,02,10);返回2020-02-10,正确值

如果您注意到1,2,则在javascript日期转换为雪花期间会增加一天。我确认JavaScript能够通过将UDF返回类型更改为VARCHAR并将日期对象返回为类似return new Date(YEAR,MONTH-1,DAY).toString()的字符串来返回正确的值,因此在转换过程中会发生一些事情。

默认情况下,JavaScript使用UTC时区,而我当前的雪花实例设置为在PST时区运行,所以认为时区方面的转换应该回到前一天,但令人惊讶的是,它却走了另一条路。

作为一种变通方法,您可以使用本机功能:

DATE_FROM_RTS

DATE_FROM_PARTS( <year>, <month>, <day> )

从表示年、月和月中日的各个数字组件中创建日期。

SELECT DATE_FROM_PARTS(1942,2,10)

为了避免Snowflake会话和JavaScript之间的奇怪时区转换,请将自己的时区设置为GMT:

ALTER SESSION SET TIMEZONE = 'America/New_York';
select JDC(1942,02,10);
# `1942-02-11` wrong
ALTER SESSION SET TIMEZONE = 'GMT';
select JDC(1942,02,10);
# `1942-02-10`, as expected.

Javascript的日期、时间和时区都很奇怪——正如您所指出的,月份是基于0的,而构造函数中的其余日期则不是。另一个问题是Javascript没有一个";日期";只有构造函数-as-Date((表示日期时间。

来自文档:

JavaScriptDate对象被转换为UDF的结果数据类型,遵循与从TIMESTAMP_LTZ(3(转换为返回数据类型相同的转换语义。https://docs.snowflake.com/en/sql-reference/udf-js.html#dates

相关内容

  • 没有找到相关文章

最新更新