Convert time PST/PDT to timestamp using Snowflake - snowflake-cloud-data-platform

Background:
I have the below table of data where I'm trying to concat the order_date and transaction_time columns to create a final timestamp column
Problem:
There is a PST/PDT string in the transaction_time column. I am trying to convert my final timestamp column(VARCHAR) into a UTC timestamp
My attempted solution that didn't work:
select
transaction_date
, to_date(transaction_date, 'mon dd, yyyy') as order_date
, transaction_time
, concat(transaction_date, ' ', transaction_time) as timestamp
-- , to_timestamp_tz(concat(transaction_date, ' ', transaction_time), 'mon dd, yyyy hh:mm:ss am pdt') as final_timestamp
from raw_db.schema_name.table_name
Please help?? Thank you!!

So PST and PDT are not valid iana timezone's which is what is expected by the Timestamp Formats, so you cannot use the inbuilt functions to handle that, but you can work around it.
SELECT time
,try_to_timestamp(time, 'YYYY-MM-DD HH12:MI:SS AM PDT') as pdt_time
,try_to_timestamp(time, 'YYYY-MM-DD HH12:MI:SS AM PST') as pst_time
,dateadd('hour',7, pdt_time) as pdt_as_utc_time
,dateadd('hour',8, pst_time) as pst_as_utc_time
,coalesce(pdt_as_utc_time, pst_as_utc_time) as utc_time1
,iff(substr(time, -3) = 'PDT', pdt_as_utc_time, pst_as_utc_time ) as utc_time2
FROM VALUES
('2020-10-28 7:25:44 AM PDT'),
-- insert more rows here...
('2020-11-06 6:35:18 PM PST')
v(time);
shows two ways to get a unified UTC time from the two.
which could be shortened to:
SELECT time
,coalesce(dateadd('hour',7, try_to_timestamp(time, 'YYYY-MM-DD HH12:MI:SS AM PDT')), dateadd('hour',8, try_to_timestamp(time, 'YYYY-MM-DD HH12:MI:SS AM PST'))) as utc_time1
,iff(substr(time, -3) = 'PDT',dateadd('hour',7, try_to_timestamp(time, 'YYYY-MM-DD HH12:MI:SS AM PDT')), dateadd('hour',8, try_to_timestamp(time, 'YYYY-MM-DD HH12:MI:SS AM PST')) ) as utc_time2
FROM VALUES
('2020-10-28 7:25:44 AM PDT'),
('2020-11-06 6:35:18 PM PST')
v(time);
which gives:
TIME UTC_TIME1 UTC_TIME2
2020-10-28 7:25:44 AM PDT 2020-10-28 14:25:44 2020-10-28 14:25:44
2020-11-06 6:35:18 PM PST 2020-11-07 02:35:18 2020-11-07 02:35:18
As Per my comment if you have more TIMEZONE you need to support, lets say New Zealand's two timeszones ;-) then a CASE would be more suitable
SELECT time
,substr(time, -4) as tz_str -- longer and NZxT is longer
,CASE
WHEN tz_str = ' PDT' THEN dateadd('hour',7, try_to_timestamp_ntz(time, 'YYYY-MM-DD HH12:MI:SS AM PDT'))
WHEN tz_str = ' PST' THEN dateadd('hour',8, try_to_timestamp_ntz(time, 'YYYY-MM-DD HH12:MI:SS AM PST'))
WHEN tz_str = 'NZDT' THEN dateadd('hour',-13, try_to_timestamp_ntz(time, 'YYYY-MM-DD HH12:MI:SS AM NZDT'))
WHEN tz_str = 'NZST' THEN dateadd('hour',-12, try_to_timestamp_ntz(time, 'YYYY-MM-DD HH12:MI:SS AM NZST'))
END as utc_time
FROM VALUES
('2020-10-28 7:25:44 AM PDT'),
('2020-11-06 6:35:18 PM PST'),
('2021-04-23 2:45:44 PM NZST'),
('2021-01-23 2:45:44 PM NZDT')
v(time);
OR you could use a regex to match up to the AM/PM part of the date time like in this SO Question/Answer, and have just one try_to_timestamp_ntz and just use the CASE to correct based of the suffix.

Related

Following date conversion query in Snowflake is not working

A varchar column in a table contains dates in '05/13/2019 20:48:13 PM' format. It can contain either a single date or many dates concatenated with pipe |. I use this query to get the very first one and try to convert it to timestamp.
Select (CASE WHEN charindex('AM', COMPL_DATE)>=1 OR charindex('PM', COMPL_DATE) >= 1
THEN TO_TIMESTAMP ( SPLIT_PART( COMPL_DATE, '|' , 1), 'MM/DD/YYYY hh24:mi:ss AM')
ELSE TO_TIMESTAMP ( SPLIT_PART( COMPL_DATE, '|' , 1), 'MM/DD/YYYY hh:mi:ss')
END
) from some_table.
I get this error
Can't parse '03/23/2019 20:56:22 PM' as timestamp with format 'MM/DD/YYYY hh24:mi:ss AM'.
It is not that it fails for all the rows. There are some rows for which it fails.
However when I use this data to run separately, like this -
with tab as ( select '03/23/2019 20:56:22 PM' COMPL_DATE from dual )
SELECT
(CASE WHEN charindex('AM',COMPL_DATE)>=1 OR charindex('PM',COMPL_DATE) >= 1
THEN TO_TIMESTAMP ( SPLIT_PART( COMPL_DATE, '|' , 1), 'MM/DD/YYYY hh:mi:ss AM')
ELSE TO_TIMESTAMP ( SPLIT_PART( COMPL_DATE, '|' , 1), 'MM/DD/YYYY hh24:mi:ss')
END
) result
FROM tab ;
It works fine.
Any help is appreciated.
Using the combination of the 24 hour clock and AM/PM is not allowed:
'MM/DD/YYYY hh24:mi:ss AM'
HH24 - Two digits for hour (00 through 23); am/pm NOT allowed.
Try: 'MM/DD/YYYY hh12:mi:ss AM'
It could be related with the extra space characters on your date string. I noticed that the web interface does not show the extra space characters in error messages so I'll contact with the development team to fix the space characters of the results in web interface.
Here's a sample query:
select TO_TIMESTAMP ( '03/23/2019 20:56:22 PM', 'MM/DD/YYYY hh24:mi:ss AM');
The error message which you will see in the web interface:
Can't parse '03/23/2019 20:56:22 PM' as timestamp with format 'MM/DD/YYYY hh24:mi:ss AM'
If you run the same query on Snowflake CLI, you can see the error clearly:
PUBLIC>select TO_TIMESTAMP ( '03/23/2019 20:56:22 PM', 'MM/DD/YYYY hh24:mi:ss AM');
100096 (22007): Can't parse '03/23/2019 20:56:22 PM' as timestamp with format 'MM/DD/YYYY hh24:mi:ss AM'
Could you verify the dates in your column?

Comparing two dates which are in different time zone

Is there a way to compare two dates (datetime datatype) which are in different time zones in SQL Server 2008 R2?
Do i need to worry about DST when converting PST to EST? Looks like there will always be 3 hour difference.
In the following script, the transaction date is in PST timezone and #Date parameter is in EST time zone;
DECLARE #Date DATETIME = '2019/03/09 00:01:57.000'
SELECT
f.[CustomerNum] ,
f.[Amount] ,
f.[TransactionDate] ,
cus.Linkdate
FROM
[Transaction] f
INNER JOIN
dbo.Customer cus ON cus.CusNum = f.CustomerNum AND cus.OID = f.OID
WHERE
f.TransactionDate > #Date
Would this work?
DATEADD(MINUTE, DATEPART(TZoffset, SYSDATETIMEOFFSET()), fpn.TransactionDate)> DATEADD(MINUTE, DATEPART(TZoffset, SYSDATETIMEOFFSET()), #Date)
The offset between PST and EST is 3 hours.
WHERE f.TransactionDate > DATEADD(hour, 3, #Date)
If your parameter is going to be time zone sensitive, it's better that you use a data type that explicitly depicts its time zone, like datetimeoffset. Then you can use switchoffset to change to the time zone you need.
DECLARE #Date DATETIMEOFFSET = '2019/03/09 00:01:57.000 -05:00' -- EST
SELECT
f.[CustomerNum] ,
f.[Amount] ,
f.[TransactionDate] ,
cus.Linkdate
FROM
[Transaction] f
INNER JOIN
dbo.Customer cus ON cus.CusNum = f.CustomerNum AND cus.OID = f.OID
WHERE
f.TransactionDate > cast(switchoffset(#Date,'-08:00') as datetime) -- PST

TO_TIMESTAMP query behaves different for same datatype columns Oracle

I have a view that I'm querying against, this view is pulling the data from 3 different tables. The curious thing is that when I execute this query:
select * from CPOB_MONITORING_DASHBOARD where FISCAL_MONTH_START_DT =
TO_TIMESTAMP('2016-01-01 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF')
it works as expected.. it returns all of the rows with a date like 2016-01-01
But when I execute a query of the same type against another column:
select * from CPOB_MONITORING_DASHBOARD where VOYAGE_STRT_DT =
TO_TIMESTAMP('2014-04-07 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF')
it returns no rows.. even if there are many dates with the value '2014-04-07'
The columns are from different tables and of type 'Date'. I can only use TO_TIMESTAMP() and not TO_DATE(). Any ideas of where do I need to look to solve this?
It looks like all your FISCAL_MONTH_START_DT values are at midnight (which seems reasonable from the column name) but your VOYAGE_STRT_DT are not - they have other times of day, so they aren't matching your query, which is only looking for exactly midnight.
select * from CPOB_MONITORING_DASHBOARD
where VOYAGE_STRT_DT >= TO_TIMESTAMP('2014-04-07 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF')
and VOYAGE_STRT_DT < TO_TIMESTAMP('2014-04-08 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF')
or more simply:
select * from CPOB_MONITORING_DASHBOARD
where VOYAGE_STRT_DT >= TIMESTAMP '2014-04-07 00:00:00'
and VOYAGE_STRT_DT < TIMESTAMP '2014-04-08 00:00:00'
or even more simply:
select * from CPOB_MONITORING_DASHBOARD
where VOYAGE_STRT_DT >= DATE '2014-04-07'
and VOYAGE_STRT_DT < DATE '2014-04-08'
though if you can't use to_date() for some reason (!?) you may not be able to use date or timestamp literals either.
You may be seeing just the date part when you query the table in other ways, which is down to your client and NLS settings. To check the times you can change your settings or explicitly format the values:
select to_char(VOYAGE_STRT_DT, 'SYYYY-MM-DD HH24:MI:SS') as VOYAGE_STRT_DT
from CPOB_MONITORING_DASHBOARD
where VOYAGE_STRT_DT >= DATE '2014-04-07'
and VOYAGE_STRT_DT < DATE '2014-04-08'

Convert mm/dd/yyyy hh:mm:ss AM into date and add minutes

I have date of birth stored in SQL server database as in this 4/23/1988 6:30:00 PM format. This column has nvarchar format. Now i want to convert this into IST which will add 5.30 hours to this date i.e output should be 4/24/1988 . It has null values also. how to do this ?
Convert() to datetime first before adding the 330 minutes
SELECT DATEADD(MINUTE, 330, CONVERT(DATETIME, date_of_birth, 101))
Try this
SELECT CAST(DATEADD(MINUTE,330,cast(date_of_birth AS datetime)) AS DATE)
Found solution....i skipped results which are null & are not valid.
Select DATEADD(MINUTE, 330, CONVERT(DATETIME, um_date_of_birth, 101)) from user_master where um_date_of_birth is not null and isdate( um_date_of_birth) <> 0

Select records created in a 24 hour time-frame

I'm trying to query our database to find all records that were created between 6am yesterday and 6am today. This will be run in a report at any point during the day so set times/dates are useless.
I have this so far:-
SELECT * FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, GetDate())
AND DATEADD(Day, 1, GetDate())
But obviously this only works for 24 hours ago from right now until right now. I can't figure out how to apply a time as well as date.
Every example I find online seems slightly different and uses set dates/times ie, >= 20/02/2015 06:00:00.
I normally use Oracle SQL which would simply work using this:-
ptt.mod_date_time >= TRUNC (SYSDATE - 1) - 2 / 24
AND ptt.mod_date_time <= TRUNC (SYSDATE - 1) + 22 / 24
This would return results from 10pm to 10pm but the format appears totally different in SQL Server.
You can get the datetime values you are after by doing the following:
SELECT DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Today6AM,
DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Yesterday6AM
By doing this: CONVERT(DATE ,GETDATE()) you are stripping off the time portion of today's date. Converting it back to datetime gives you midnight for today.
The query adds 6 hours to midnight of the current day for 6am today and subtracts 18 hours from midnight of the current day to give you 6am on the previous day.
Output:
Today6AM Yesterday6AM
================================================
2015-02-20 06:00:00.000 2015-02-19 06:00:00.000
So adding that to your query:
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime
BETWEEN DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
AND DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
DECLARE #StartTimestamp datetime
DECLARE #EndTimestamp datetime
DECLARE #HourPartOfSearchRange nvarchar(6)
SET #HourPartOfSearchRange = ' 06:30'
SET #StartTimestamp =
CAST((CONVERT(varchar(11), DATEADD(DAY,-1,#CurrentUTCDateTime), 106) + #HourPartOfSearchRange) AS datetime)
SET #EndTimestamp =
CAST((CONVERT(varchar(11), #CurrentUTCDateTime, 106) + #HourPartOfSearchRange) AS datetime)
SELECT * FROM dbo.Test Where Timestamp Between #StartTimestamp AND #EndTimestamp
today 6am is
dateadd(hour,6,cast(cast(getdate() as date) as datetime))
cast(getdate() as date) truncates the timepart, cast it back as datetime because dateadd won't add hours otherwise and add 6hours
One solution would be like so:
select *
from DaySummaryDetail DSD
where DSD.FromDateTime between cast(cast(cast(getdate()-1 as date) as varchar(30)) + ' 06:00:00.000' as datetime)
and cast(cast(cast(getdate() as date) as varchar(30)) + ' 06:00:00.000' as datetime)
This should help ...
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE(), AS Date) AS DateTime) ) AS 'Today#6am'
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE()-1, AS Date) AS DateTime) ) AS 'Yesterday#6am'
In SQL Server 2012 you can use SMALLDATETIMEFROMPARTS to construct a datetime value that is today at 6am like this:
SMALLDATETIMEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()), 6, 0)
Output: 2015-02-20 06:00:00
then you can use the above expression in place of GETDATE() in the WHERE clause:
DECLARE #TodayAt6AM DATETIME = SMALLDATETIMEFROMPARTS(YEAR(GETDATE()),
MONTH(GETDATE()),
DAY(GETDATE()),
6,
0)
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, #TodayAt6AM) AND
DATEADD(Day, 1, #TodayAt6AM)

Resources