The default JavaScript Date.toString()
representation converts the date to a string in a format that is non-standard. Also, to use a Date
constructor ensure you pass the new
keyword as otherwise Date
acts as a function that rejects invalid inputs and silently returns the current date.
> console.log(Date("Sun Jul 29 2018 00:00:00 GMT-0700 (PDT)"))
"Mon Jun 29 2020 01:16:31 GMT-0700 (PDT)"
> console.log(new Date("Sun Jul 29 2018 00:00:00 GMT-0700 (PDT)"))
"Sun Jul 29 2018 00:00:00 GMT-0700 (PDT)"
When using the default Date string formatting from JavaScript in SQL to be cast as date or timestamp types, Snowflake only recognises standard formatted strings, and will reject JS date strings of the form Sun Jul 29 2018 00:00:00 GMT-0700 (PDT)
. Use Date.toISOString()
instead to produce a usable representation that will work with Snowflake SQL types.
Furthermore, the binds argument in snowflake.createStatement(…)
must always be an array of elements, even when you are planning to pass only a single element to it. That is, supply binds: [convertedRunningDate]
instead of binds: convertedRunningDate
.
Combining the two above points, here's an example that shows how to manipulate the date within JavaScript from one table to another.
create or replace table source_table(datecol date) as select current_date;
create or replace table dest_table (datecol date);
CREATE OR REPLACE PROCEDURE insert_date_plus_one()
RETURNS boolean
LANGUAGE JAVASCRIPT
AS
$$
// Grab a datecol from a select query
var source_date_stmt = snowflake.createStatement(
{
sqlText: "select datecol from source_table"
}
);
var source_resultset = source_date_stmt.execute();
source_resultset.next();
// This is of type SfDate because it came from a query ResultSet,
// so we can apply standard JS Date functions over it
var source_date = source_resultset.getColumnValue(1);
// Function to increment a Date object by one standard day
// Sourced from https://stackguides.com/questions/563406/add-days-to-javascript-date
function addDaysInJs(date, days) {
var result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
var dest_date = addDaysInJs(source_date, 1);
// Insert the incremented date using its ISO representation string
// which will allow Snowflake to grok it properly
var dest_date_stmt = snowflake.createStatement(
{
sqlText: "insert into dest_table values (?)"
,binds: [dest_date.toISOString()]
}
);
var dest_resultset = dest_date_stmt.execute();
var did_insert_run = dest_resultset.next();
return did_insert_run;
$$ ;
call insert_date_plus_one();
This yields the result:
> select * from source_table;
+------------+
| DATECOL |
|------------|
| 2020-06-29 |
+------------+
> select * from dest_table;
+------------+
| DATECOL |
|------------|
+------------+
> call insert_date_plus_one();
+----------------------+
| INSERT_DATE_PLUS_ONE |
|----------------------|
| TRUE |
+----------------------+
> select * from dest_table;
+------------+
| DATECOL |
|------------|
| 2020-06-30 |
+------------+
If you need to arbitrarily use Date
objects instead of sourcing it from a table row, just ensure you are constructing them properly (with new
), and when binding use its Date.toISOString()
method instead of passing it as-is (default toString()
produces an incompatible format).
Note: Where possible, try to manipulate it over SQL and just extract results so you do not have to work with two different date/time type systems.
Further reading: