Why Bigquery TIMESTAMP_TRUNC function is having such behavior when using timezones? - google-bigquery

Is there anyone who can explain this behavior :
SELECT TIMESTAMP_TRUNC(TIMESTAMP(FORMAT_TIMESTAMP("%F %T", '2022-12-17 23:50:50.000000 UTC')), DAY, "UTC-1") --2022-12-17 01:00:00 UTC
SELECT TIMESTAMP_TRUNC(TIMESTAMP(FORMAT_TIMESTAMP("%F %T", '2022-12-17 23:50:50.000000 UTC')), DAY, "UTC") --2022-12-17 00:00:00 UTC
SELECT TIMESTAMP_TRUNC(TIMESTAMP(FORMAT_TIMESTAMP("%F %T", '2022-12-17 23:50:50.000000 UTC')), DAY, "UTC+1") --2022-12-17 23:00:00 UTC
SELECT TIMESTAMP_TRUNC(TIMESTAMP(FORMAT_TIMESTAMP("%F %T", '2022-12-17 23:50:50.000000 UTC')), DAY, "UTC+2") --2022-12-17 22:00:00 UTC
SELECT TIMESTAMP_TRUNC(TIMESTAMP(FORMAT_TIMESTAMP("%F %T", '2022-12-17 23:50:50.000000 UTC+2')), DAY, "UTC+2") --2022-12-16 22:00:00 UTC
It seems that google does not provide enough explanation or examples to get this straight.
My questions are :
what is the use of the timezone as argument in TIMESTAMP_TRUNC if it
can be specified in the timestamp expression itself.
if would be great if someone details their explanation with what the
timezone in the timestamp value means, the timezone as 3rd argument
in the TIMESTAMP_TRUNC function means, and the UTC in the result
means
Thanks guys!

With the help of my collegue here is an explanation of what is happening when using TIMESTAMP_TRUNC:
SELECT TIMESTAMP_TRUNC(TIMESTAMP(FORMAT_TIMESTAMP("%F %T", '2022-12-17 23:50:50.000000 UTC')), DAY, "UTC+1") --2022-12-17 23:00:00 UTC
ask yourself this question : what is its equivalent in UTC+1 ( third argument) ? => '2022-12-18 00:50:50 UTC+1'
truncate at day level (result will be in UTC+1) '2022-12-18 00:00:00 UTC+1'
ask yourself this question : what is its equivalent in UTC ? => '2022-12-17 23:00:00 UTC
It may seem obvious for you but if someone gets stuck with it one day I hope they this will help

Related

Unexpected result from Redshift TIMEZONE function (convert timestamp column from UTC to another timezone)

Based on my understanding of the documentation, I am expecting the TIMEZONE function to convert any timestamp from UTC (by default) to 'timezone'.
I know for a fact that the timestamp columns of the server I'm pulling data from are set to UTC. Therefore, if I convert the timestamp column to EST, I should see a five hour difference between UTC and EST (according to worldtimebuddy).
However, when I run the following query
select
time_column
, timezone('est', time_column) as to_est
from
my_table
order by
time_column desc
limit 1
I get
sent_at
to_est
2022-11-15 17:50:26.280
2022-11-15 22:50:26.280
If I'm interpreting this correctly, the result is telling me that UTC is five hours behind EST, when really, UTC is five hours ahead of EST (right?).
In other words, I was expecting
sent_at
to_est
2022-11-15 17:50:26.280
2022-11-15 12:50:26.280
Why am I seeing a -5 hour difference from UTC to EST instead of +5?
instead of timezone use
convert_timezone('EST', time_column)
That is the way redshift shows in the manual
the syntax is
CONVERT_TIMEZONE ( ['source_timezone',] 'target_timezone', 'timestamp')
but the source time zone is by default UTC, so you don't need to add it to your code

How to show real time difference between timestamps in two different zones with SQL?

This query returns 0
SELECT (CURRENT_TIMESTAMP AT TIME ZONE 'PST'
- CURRENT_TIMESTAMP AT TIME ZONE 'UTC') AS td
FROM dual
How can I make it to actually show the real difference in time? For example, in this case I want to see a difference of -8 hours.
In this example I used CURRENT_TIMESTAMP, but I have a real use case where I have timestamps in two different time zones. And I want the real time difference between those two.
Cast the values to a TIMESTAMP without a time zone:
SELECT CAST(CURRENT_TIMESTAMP AT TIME ZONE 'PST' AS TIMESTAMP)
- CAST(CURRENT_TIMESTAMP AT TIME ZONE 'UTC' AS TIMESTAMP)
as td
FROM DUAL;
Which outputs:
TD
-000000000 08:00:00.000000
Or, considering times around the DST boundary:
-- Times around the DST boundary.
WITH times (t) AS (
SELECT TIMESTAMP '2021-03-14 09:30:00 UTC' FROM DUAL UNION ALL
SELECT TIMESTAMP '2021-03-14 10:30:00 UTC' FROM DUAL
)
SELECT t As t_utc,
t AT TIME ZONE 'PST8PDT' AS t_pstpdt,
(CAST(t AT TIME ZONE 'PST8PDT' AS TIMESTAMP)
- CAST(t AT TIME ZONE 'UTC' AS TIMESTAMP)) AS td
FROM times
Outputs:
T_UTC
T_PSTPDT
TD
2021-03-14 09:30:00.000000000 UTC
2021-03-14 01:30:00.000000000 PST8PDT
-000000000 08:00:00.000000
2021-03-14 10:30:00.000000000 UTC
2021-03-14 03:30:00.000000000 PST8PDT
-000000000 07:00:00.000000
db<>fiddle here
So, you want to find the time difference between the time zones. (This is not what the title says; the title is misleading.)
If so, then you don't need to reference current_timestamp, or anything of the kind.
Since you are comparing PST to UTC, this is the same as finding the UTC offset of PST. This makes the problem even easier. (In the general case, you can find the offset of both time zones and subtract; in your example, the offset of UTC to itself is zero, obviously).
select to_char(to_timestamp_tz('PST', 'tzr'), 'tzh:tzm') as pst_offset
from dual;
PST_OFFSET
----------
-08:00

Repeating time (1 AM-1:59:59 AM) on first Sunday of November - Daylight Savings ending day - Oracle

Good afternoon.
I understand that there is "each second of each minute of one specific hour" is repeated (1 AM - 1:59:59 AM) on first Sunday of November (Closing day of Daylight Saving time). So, duration from 0:00 AM (midnight) to 3 AM is 4 hours on that day.
SELECT TO_TIMESTAMP_TZ('2021-11-07 03:00:00 US/Mountain',
'yyyy-mm-dd hh24:mi:ss TZR')
- TO_TIMESTAMP_TZ('2021-11-07 00:00:00 US/Mountain', 'yyyy-mm-dd hh24:mi:ss TZR') FROM DUAL;
The above query is returning 4 hours as expected.
Here is my question -
I want to basically differentiate/represent the two occurrences of 1 AM (or any time between 1 AM, and 1:59:59 AM). How can I do? (I am using Oracle 12.1)
BTW, this following query is resulting 1 hour 30 minutes, so '2021-11-07 01:30:00 MST' represents the second instance of 1:30 AM. In the same manner, I was expecting '2021-11-07 01:30:00 MDT' to be the first instance, however it is resulting ORA-01882: timezone region not found. BTW, I prefer to have US/Mountain (or something like that) for region, rather MST vs. MDT
SELECT TO_TIMESTAMP_TZ('2021-11-07 03:00:00 MST', 'yyyy-mm-dd
hh24:mi:ss TZR')
- TO_TIMESTAMP_TZ('2021-11-07 01:30:00 MST', 'yyyy-mm-dd hh24:mi:ss TZR') FROM DUAL;
Sorry if I confused you. Please let me know if any questions.
Any help?
Thank you
Viswa
Added later:
I think I found the answer: We need to use TZD flag, and use MST/MDT values.
I did not like that as I prefer to use the region (such as US/Mountain).
So any enhancements will be appreciated.
SELECT TO_TIMESTAMP_TZ('2021-11-07 03:00:00 US/Mountain',
'yyyy-mm-dd hh24:mi:ss TZR')
- TO_TIMESTAMP_TZ('2021-11-07 00:00:00 US/Mountain', 'yyyy-mm-dd hh24:mi:ss TZR') FROM DUAL;
-- 4 hours:00 minutes, as expected
SELECT TO_TIMESTAMP_TZ('2021-11-07 03:00:00 MST', 'yyyy-mm-dd
hh24:mi:ss TZD')
- TO_TIMESTAMP_TZ('2021-11-07 01:30:00 MDT', 'yyyy-mm-dd hh24:mi:ss TZD') FROM DUAL;
-- 2:30 minutes
-- So any values ranging from 1:00 to 1:59:59 with a time zone of MDT are the first instance values.
SELECT TO_TIMESTAMP_TZ('2021-11-07 03:00:00 MST', 'yyyy-mm-dd
hh24:mi:ss TZD')
- TO_TIMESTAMP_TZ('2021-11-07 01:30:00 MST', 'yyyy-mm-dd hh24:mi:ss TZD') FROM DUAL;
-- 1 hour:30 minutes
-- So any values ranging from 1:00 to 1:59:59 with a time zone of MST are the second instance values.
Value TIMESTAMP '2021-11-07 01:00:00 US/Mountain' is ambiguous, it could be
2021-11-07 01:00:00-06:00 or 2021-11-07 01:00:00-07:00
If you don't specify the daylight-saving-time status then Oracle defaults to the standard time, (MST in your case)
You need to provide both, the timezone region and the Daylight Saving Time information, i.e. TO_TIMESTAMP_TZ('2021-11-07 01:00:00 US/Mountain MST', 'yyyy-mm-dd hh24:mi:ss TZR TZD') or TO_TIMESTAMP_TZ('2021-11-07 01:00:00 US/Mountain MDT', 'yyyy-mm-dd hh24:mi:ss TZR TZD')
Note, if you alter your session with ALTER SESSION SET ERROR_ON_OVERLAP_TIME = TRUE; then for ambiguous times like TIMESTAMP '2021-11-07 01:00:00 US/Mountain' Oracle does not default to standard time but raise an error:
ORA-01883: overlap was disabled during a region transition
Don't mistake "Time zone region" (TRZ) with "Daylight saving information" (TZD), however MST can mean both:
SELECT *
FROM V$TIMEZONE_NAMES
WHERE TZABBREV in ('MST', 'MDT');
Calculations of TIMESTAMP WITH TIME ZONE values are internally always performed on UTC times.
See Support for Daylight Saving Time

parse_timestamp vs format_timestamp bigquery

Could someone help me understand why these two queries are returning different results in bigquery?
select FORMAT_TIMESTAMP('%F %H:%M:%E*S', "2018-10-01 00:00:00" , 'Europe/London')
returns 2018-10-01 01:00:00
select PARSE_TIMESTAMP('%F %H:%M:%E*S', "2018-10-0100:00:00", "Europe/London")
returns 2018-09-30 23:00:00 UTC
As 2018-10-01 is during british summer time (UTC +1), I would've expected both queries to return 2018-09-30 23:00:00 UTC
The first is given a timestamp which is in UTC. It then converts it to the corresponding time in Europe/London. The return value is a string representing the time in the local timezone.
The second takes a string representation and returns a UTC timestamp. The representation is assumed to be in Europe/London.
So, the two functions are going in different directions, one from UTC to the local time and the other from the local time to UTC.

how to get EST and UTC irrespective of Day

I have to show EST/EDT and GMT/UTC using Oracle 10g.The issue is on Nov 2nd UTC difference will change '+ 05' hour which will cause my jobs to fail.Please let me know how to fix it without manually changing interval to 5 hours.I have tried new_time function but that does not solve the problem. The all columns are DATE datatype.
SELECT PROCESS_NAME,
date_modified as EST_DATE_MODIFIED,
date_modified + interval '+ 04' hour as GMT_DATE_MODIFIED
FROM tbl_process_status ;
Result
EST_DATE_MODIFIED GMT_DATE_MODIFIED
22-OCT-14 11:08:25 22-OCT-14 03:08:25
Thanks Ed but above query is not returning correct UTC time.
EST - 22-OCT-14 12:19:55
Correct UTC- 22-OCT-14 04:19:55
Above Query UTC 22-OCT-14 08:19:55
select (TO_NUMBER(TO_CHAR(CURRENT_TIMESTAMP, 'TZH')) * INTERVAL '1' HOUR) from dual;
-0 4:0:0.0
Thanks Multisync.
I got below result but I need data only in DD-MON-YY HH:MM:SS Format.
Expected 22-OCT-14 12:19:55
Expected 22-OCT-14 04:19:55
Result 22-OCT-14 12.19.55.000000000 PM AMERICA/NEW_YORK
Result 22-OCT-14 04.19.55.000000000 PM UTC
select systimestamp at time zone 'est' for_timestamp,
cast(sysdate as timestamp) at time zone 'est' for_date,
cast(sysdate as timestamp) at time zone 'gmt' gmt_timezone
from dual;
So you can try this (edited according to the comments)
SELECT PROCESS_NAME,
cast(cast(date_modified as timestamp) at time zone 'America/New_York' as date) as EST_DATE_MODIFIED,
cast(cast(date_modified as timestamp) at time zone 'UTC' as date) as GMT_DATE_MODIFIED
FROM tbl_process_status;