Snowflake datetime conversion - snowflake-cloud-data-platform

I have a stored procedure that has a parameter called rundate. If I use this parameter in my stored procedure I get date like Tue May 03 2022 08:37:42 GMT-0500 (Central Daylight Time) which is not allowing for me to perform any manipulation.
How to convert this data (with Javascript stored procedure) to valid TZ datetime like
2022-05-03 15:07:21.000 +0000?
Please advise
var strsql = `
SELECT
WHEN j_date >RUN_DATE THEN RUN_DATE
ELSE j_date
FROM table
where col1 = 'ABC'
;
`;
// Run the statement.
var sql = snowflake.createStatement({sqlText: strsql });
var result = sql.execute();
result.next();

You should be able to convert to a timestamp with your specific mask format. This site has a reference of all the formats you can specify: https://docs.snowflake.com/en/user-guide/date-time-input-output.html#timestamp-formats. I am presuming your date column is currently a string
the SQL statement you have above needed a CASE and END to properly execute.
Please see demo table below
create or replace table table_a (j_date varchar, run_date varchar, col1 varchar);
INSERT INTO table_a (SELECT 'Tue May 03 2022 08:37:42 GMT-0500', 'Tue May 03 2022 08:37:42 GMT-0500' ,'ABC') ;
With this, you can then wrap a TO_TIMESTAMP around your date column and see both results side by side
SELECT CASE
WHEN J_DATE > RUN_DATE THEN RUN_DATE
ELSE j_date
END new_col,
to_timestamp(new_col,'DY MON DD YYYY HH24:MI:SS GMT-TZHTZM') new_col_formatted
FROM table_a
where col1 = 'ABC';
NEW_COL
NEW_COL_FORMATTED
Tue May 03 2022 08:37:42 GMT-0500
2022-05-03 08:37:42.000

The problem is that inside Javascript the default representation of a date is not compatible with the SQL side of the game. Made worse is the fact that the Javascript runtime cares about the timezone of the server, which for some horrific reason is not UTC, so you will get different values to region.
If you need to pass DATE types into the SP/Function pass it as string from the SQL side, so the date will already be formatted as you want it, and just string compose that into your SQL:
You can even see this in the stock Javascript SP example: the date is passed as a string..
I was working up an example to show this:
create database test;
use schema test.public;
create table test.public.table1(id number, date date);
INSERT INTO test.public.table1
SELECT * FROM VALUES
(1, '2022-01-01'),
(2 , '2022-02-01'),
(3 , '2022-02-05');
create or replace procedure date_handler(rundate DATE)
returns string
language javascript
as
$$
let strsql = `select sum(id) from test.public.table1 where date >= '`+ RUNDATE +`'`;
return strsql;
$$;
call date_handler('2020-01-01'::date);
DATE_HANDLER
select sum(id) from test.public.table1 where date >= 'Wed Jan 01 2020 00:00:00 GMT-0800 (Pacific Standard Time)'
create or replace procedure string_handler(rundate text)
returns string
language javascript
as
$$
let strsql = `select sum(id) as a from test.public.table1 where date >= '`+ RUNDATE +`'`;
return strsql;
$$;
call string_handler('2020-01-01'::date);
STRING_HANDLER
select sum(id) as a from test.public.table1 where date >= '2020-01-01'
select sum(id) as a from test.public.table1 where date >= '2020-01-01';
A
6
But was shocked the doc's show this, but don't appear to mention it directly..

The simplest thing to use is the .toISOString() method for JavaScript dates.
create or replace procedure JAVASCRIPT_DATE("inputDate" date)
returns string
language javascript
as
$$
return inputDate;
$$;
call JAVASCRIPT_DATE('2022-05-04'::date);
-- Returns Wed May 04 2022 00:00:00 GMT+0000 (Coordinated Universal Time)
create or replace procedure ISO_DATE("inputDate" date)
returns string
language javascript
as
$$
return inputDate.toISOString();
$$;
call ISO_DATE('2022-05-04'::date);
-- Returns 2022-05-04T00:00:00.000Z
Although the .toISOString() method adds a T between the date and time, Snowflake will parse it just fine. The time will be represented in UTC this way. If that's not what you want, be sure to adjust for time zone.

Related

Convert Wed Oct 14 08:00:00 CDT 2020 format to DateOnly and Time Only

We receive a csv file that has a column in this date format -- Wed Oct 14 08:00:00 CDT 2020, along with a column that has a count for each date/time
I am using an SSIS package to grab the file and import this data into a sql table, then I can format it the way I need to and then actually export the data in the format needed.
If there is a way to do this all within one SSIS package I am all ears but currently I am working on just getting the data into SQL and converted to the right format so that I can export it.
I need to get that file and convert that date format and split it up into two separate columns
One column will be just the date in this format 2020-10-14 00:00:00.000
One column will be just the time in this format 08:00:00.0000000
Updated to change the dates to match so it's not as confusing and also the error I am receiving when running the suggested code below.
Image of Error I'm recieving
Image of table with the data I am trying to convert
Image of table attributes
Screenshot of my screen when running a select * from the table I am pulling the data that I need converted
Screenshot of the error I receive when running the query by Aaron.
If this is the format it will always be in, and timezone is irrelevant, you can first try to convert it to a datetime, then you can extract the parts from that.
SET LANGUAGE us_english; -- important because not all languages understand "Oct"
;WITH src AS
(
SELECT dt = TRY_CONVERT(datetime, RIGHT(OpenedDateTime ,4)
+ SUBSTRING(OpenedDatetime, 4, 16))
--, other columns...
FROM [dbo].[VIRTUALROSTERIMPORT_Res_Import]
)
SELECT OpenedDateTime = CONVERT(datetime, CONVERT(date, dt)),
OnHour = CONVERT(time, dt)
--, other columns...
FROM src;
Results:
OpenedDateTime OnHour
-------------- ----------------
2020-10-14 08:00:00.0000000
If you need to shift from one timezone to another timezone, that's a different problem.
I was just showing the date formats, don't look so into the actual date examples I used. The time zone is irrelevant I just need the formats changed.
When I used The code Aaron suggested I got a conversion error: I'm assuming its because the columns are varchar in the table, but I cant get the dates to load as date formats bc SSIS keeps giving me truncated errors-- so I have to load it as varchar.
Below is the code I was running, I tweaked it to use the column and table names I am using.
SET LANGUAGE us_english; -- important because not all languages understand "Oct"
DECLARE #foo varchar(36) = 'Wed Oct 14 08:00:00 CDT 2020';
;WITH src(d) AS
(
SELECT TRY_CONVERT(datetime, RIGHT(#foo,4) + SUBSTRING(#foo, 4, 16))
)
SELECT OpenedDateTime = CONVERT(datetime, CONVERT(date, OpenedDateTime)),
onhour = CONVERT(time, OpenedDateTime)
FROM [dbo].[VIRTUALROSTERIMPORT_Res_Import];

SQL Server returns different result for the same Date selection query, In different scenarios

I was trying to get a date based on Timezone and I was nearly successful with that. But I got an issue when I incorporate that query with the stored procedure.
Here is the code which gives me the correct output.
DECLARE
#TimeZone VARCHAR(100) = 'India Standard Time'
declare #EndDate DATETIME = (SELECT (CONVERT( datetime,SYSDATETIMEOFFSET() AT TIME ZONE #TimeZone)))
select #EndDate
and the output is (correct o/p)
2019-12-23 20:43:18.020
Then I incorporate it with a stored procedure
which comes under an if condition
O/P is like this
Dec 23 2019 8:38PM
can anybody help me with this
The value of the variable looks correct but just shown in different format. You can force it to show in the format you want:
select CONVERT(nvarchar(100),#EndDate,120) as EndDate;

there were some errors in the query: RequestError: Conversion failed when converting date and/or time from character string

i am using MS SQL Server 2008 when i run this query
select top 1 * from table_name where ModifiedDate='Wed Mar 16 2016 15:52:20 GMT+0530 (IST)'
i get this error
there were some errors in the query: RequestError: Conversion failed when converting date and/or time from character string.
i also tried CAST and CONVERT but having same error
i am using node mssql client
To answer the question directly, use this instead:
select top 1 * from table_name where ModifiedDate=cast('2016-03-16 15:52:20 +05:30' as datetimeoffset)
Now the explanation. To use timezones, you need to use datetimeoffset - regular datetime fields don't include timezone info. So, this will work:
select cast('2016-7-16 15:52:20 +05:30' as datetimeoffset)
Using AdventureWorks2012 (this syntax will also work in sql 2008, but this is demoing how you'd write this query against the AW2012 database):
select top 1 * from Person.Address where ModifiedDate=cast('2002-01-04 00:00:00 +00:00' as datetimeoffset)
Note in this case, AW2012 uses a datetime field, but not a datetimeoffset field in this table - nevertheless, it compiles and runs.
The next example demonstrates how the timezone offset works:
select top 1 * from Person.Address where ModifiedDate=cast('2002-01-04 04:00:00 +04:00' as datetimeoffset)
This returns a value, whereas changing the offset by 1 hour returns no result. (There's one record with a ModifiedDate of 2002-01-04 00:00:00 in the table):
select top 1 * from Person.Address where ModifiedDate=cast('2002-01-04 04:00:00 +03:00' as datetimeoffset)

Query epoch time using SQL Server to find date range

I have to query an SQL Server database and the table's values use Epoch time (an int. Here's an example - 1438005018). I am wondering how I can write a query so that I can say the following...
select
*
from
tablename
where
epochdate between 'yesterday at 12:00' and 'today at 12:00' --this is the part I'm not sure about.
Ideally, if it's easy, I'd like the query to use non-epoch logic as Epoch time confuses the crap out of me. Maybe there's a quick way of converting in SQL Server?
I posted a link above in the comments that may be a more practical solution if you're able to deploy functions in the database you're working with, but if you're only able to query, this is an option to try as well (this assumes SQL Server 2008 and above):
declare #todayepoch bigint, #yesterdayepoch bigint;
select #todayepoch =
cast((cast(dateadd(hour, 12,
cast(cast(sysutcdatetime() as date) as datetime)) as decimal(24,10))
- cast(cast('1970-01-01' as datetime) as decimal(24,10)))
*60.0*60.0*24.0 as int), -- + 18000, --Eastern time
#yesterdayepoch =
cast((cast(dateadd(hour, -12,
cast(cast(sysutcdatetime() as date) as datetime)) as decimal(24,10))
- cast(cast('1970-01-01' as datetime) as decimal(24,10)))
*60.0*60.0*24.0 as int) -- + 18000 --Eastern time
select #todayepoch, #yesterdayepoch
select
*
from
tablename
where
epochdate between #yesterdayepoch and #todayepoch
I used UTC above as a presumption of comparing based on UTC times, but you could also compare to your time zone, with the appropriate addition/subtraction of your time zone difference in seconds (e.g., add 18000 to each variable to get noon in Eastern Standard Time).
You can test your results by using http://www.epochconverter.com/ to compare your values in your variables.
You query would look like the following:
DECLARE #dt_from DATETIME;
DECLARE #dt_to DATETIME;
SELECT
#dt_from=DATEADD(HH,-12,CAST(FLOOR(CAST(GETUTCDATE() AS FLOAT)) AS DATETIME)), -- strip time of current UTC date/time, and subtract 12 hrs
#dt_to=DATEADD(HH,+12,CAST(FLOOR(CAST(GETUTCDATE() AS FLOAT)) AS DATETIME)); -- strip time of current UTC date/time, and add 12 hrs
SELECT
*
FROM
tablename
WHERE
epochdate BETWEEN DATEDIFF(s,'1970-01-01',#dt_from) AND DATEDIFF(s,'1970-01-01',#dt_to);

SQL Server function to return minimum date (January 1, 1753)

I am looking for a SQL Server function to return the minimum value for datetime, namely January 1, 1753. I'd rather not hardcode that date value into my script.
Does anything like that exist? (For comparison, in C#, I could just do DateTime.MinValue)
Or would I have to write this myself?
I am using Microsoft SQL Server 2008 Express.
You could write a User Defined Function that returns the min date value like this:
select cast(-53690 as datetime)
Then use that function in your scripts, and if you ever need to change it, there is only one place to do that.
Alternately, you could use this query if you prefer it for better readability:
select cast('1753-1-1' as datetime)
Example Function
create function dbo.DateTimeMinValue()
returns datetime as
begin
return (select cast(-53690 as datetime))
end
Usage
select dbo.DateTimeMinValue() as DateTimeMinValue
DateTimeMinValue
-----------------------
1753-01-01 00:00:00.000
Have you seen the SqlDateTime object? use SqlDateTime.MinValue to get your minimum date (Jan 1 1753).
As I can not comment on the accepted answer due to insufficeint reputation points my comment comes as a reply.
using the select cast('1753-1-1' as datetime) is due to fail if run on a database with regional settings not accepting a datestring of YYYY-MM-DD format.
Instead use the select cast(-53690 as datetime) or a Convert with specified datetime format.
Enter the date as a native value 'yyyymmdd' to avoid regional issues:
select cast('17530101' as datetime)
Yes, it would be great if TSQL had MinDate() = '00010101', but no such luck.
Here is a fast and highly readable way to get the min date value
Note: This is a Deterministic Function, so to improve performance further we might as well apply WITH SCHEMABINDING to the return value.
Create a function
CREATE FUNCTION MinDate()
RETURNS DATETIME WITH SCHEMABINDING
AS
BEGIN
RETURN CONVERT(DATETIME, -53690)
END
Call the function
dbo.MinDate()
Example 1
PRINT dbo.MinDate()
Example 2
PRINT 'The minimimum date allowed in an SQL database is ' + CONVERT(VARCHAR(MAX), dbo.MinDate())
Example 3
SELECT * FROM Table WHERE DateValue > dbo.MinDate()
Example 4
SELECT dbo.MinDate() AS MinDate
Example 5
DECLARE #MinDate AS DATETIME = dbo.MinDate()
SELECT #MinDate AS MinDate
It's not January 1, 1753 but select cast('' as datetime) wich reveals: 1900-01-01 00:00:00.000 gives the default value by SQL server.
(Looks more uninitialized to me anyway)
This is what I use to get the minimum date in SQL Server. Please note that it is globalisation friendly:
CREATE FUNCTION [dbo].[DateTimeMinValue]()
RETURNS datetime
AS
BEGIN
RETURN (SELECT
CAST('17530101' AS datetime))
END
Call using:
SELECT [dbo].[DateTimeMinValue]()
What about the following?
declare #dateTimeMin as DATETIME = datefromparts(1753, 1, 1);
select #dateTimeMin;
The range for datetime will not change, as that would break backward compatibility. So you can hard code it.

Resources