SQL - Creating UTC Timestamp from separate date/time/timezone information - sql

I'm working with BigQuery and have a table that looks like:
YEAR
MONTH
DAY
timezone
local time
2015
6
24
America/Los Angeles
1930
Where local time is given by hhmm. I'm wondering if I can format this information into a timestamp column in SQL that yields time in UTC.
I know I can use `TO_TIMESTAMP` but that would involve concatenating all these columns as strings first. Is there any better way to do this? If I were to concatenate, I'm not sure how I would use timezone and then back out UTC.

You might consider below.
WITH sample_table AS (
SELECT 2015 year, 6 month, 24 day, 'America/Los_Angeles' timezone, 1930 local_time UNION ALL
SELECT 2015 year, 6 month, 24 day, 'America/Los_Angeles' timezone, 2400 local_time
)
SELECT TIMESTAMP_SECONDS(
UNIX_SECONDS(TIMESTAMP(DATE(year, month, day), timezone))
+ DIV(local_time, 100) * 3600 + MOD(local_time, 100) * 60
) utc
FROM sample_table;
Since TIME(24, 0, 0) is not a valid time format, the query converts datetime into unix seconds and get back to UTC with the time calculation in seconds.
Input calculates to invalid time: 24:00:00
Query results

Related

how to get Date difference in postgres with date part

How to get datetime difference in postgres
I am using below syntax
DATE_PART('hour', A_column::timestamp-B_column::timestamp )
I want output like this:
If A_column=2020-05-20 00:00:00 and B_column=2020-05-15 00:00:00 I want to get 72(in hours).
Is there any possibility to skip weekends(Saturday and Sunday) in first one, it means to get the result as 72 hours(exclude weekend hours)
If A_column=2020-08-15 12:00:00 and B_column=2020-08-15 00:00:00 I want to get 12(in hours).
You could write this as:
select extract(epoch from a_column::timestamp - b_column::timestamp) / 60 / 60
from mytable
Rationale: substracting the two timestamps gives you an interval; you can then turn it to a number of seconds, and do arithmetics to convert that to hours.

how can I subtract time from a date time field to adjust a date time field?

I currently have a datetime field in the following format: "2019-07-07 15:00:00 UTC". However, this date is an hour and 25 minutes ahead of what it should be. How can I subtract 1 hour and 25 minutes from this time in a new time field?
E.g., "I need 2019-07-07 15:00:00 UTC" to become "2019-07-07 13:35:00 UTC"
Language: SQL
Database: Pulling using Bigquery, which pulls from Google Cloud
The attached image shows the part of my SELECT statement I am working with. The first line is the date but in the database string form, the second line converts it to a date, and the third is trying to transform the date to subtract an hour and 25 mins.
Thanks in advance for the help!
You can try the below for subtracting Hours
SELECT TIMESTAMP_SUB(TIMESTAMP "2019-07-07 15:00:00 UTC", INTERVAL 1 HOUR)
Change your interval accordingly. In your case you can convert it into minutes and then use the MINUTE INTERVAL as shown below
SELECT TIMESTAMP_SUB(starts_at, INTERVAL 85 MINUTE)

How to get date of yesterday with the time part 00:00:00 in big query?

In big query how do I get the yesterday date with the time part 00:00:00?
DATE Doesn't have time part
if you want yesterday DateTime with 00:00 as time use:
SELECT DATETIME_TRUNC(DATETIME_SUB(CURRENT_DATETIME(), INTERVAL 1 DAY), DAY) as yesterday;
if you want yesterday date use:
SELECT DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY) as yesterday;
If you want a time part, then you want either a TIMESTAMP or DATETIME column.
So, either:
SELECT DATETIME(DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) as yesterday_dt,
TIMESTAMP(DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) as yesterday_ts
This code gets you date
SELECT DATEADD(dd, -1, DATEDIFF(dd, 0, GETDATE()));
For different methods check this link
MS SQL Server - How to get Date only from the datetime value?
Below is yet another option for BigQuery standard SQL
#standardSQL
SELECT
TIMESTAMP_SECONDS(86400 * (UNIX_DATE(CURRENT_DATE()) - 1)) yesterday_as_timestamp,
DATETIME(TIMESTAMP_SECONDS(86400 * (UNIX_DATE(CURRENT_DATE()) - 1))) yesterday_as_datetime
with result (as of answer day - April 02, 2019)
Row yesterday_as_timestamp yesterday_as_datetime
1 2019-04-01 00:00:00 UTC 2019-04-01T00:00:00
Note:
DATETIME Represents a year, month, day, hour, minute, second, and subsecond. Range: 0001-01-01 00:00:00 to 9999-12-31 23:59:59.999999.
TIMESTAMP Represents an absolute point in time, with microsecond precision. Range: 0001-01-01 00:00:00 to 9999-12-31 23:59:59.999999 UTC.
A timestamp represents an absolute point in time, independent of any time zone or convention such as Daylight Savings Time.
TIMESTAMP provides microsecond precision.
Unlike Timestamps, a DATETIME object does not refer to an absolute instance in time. Instead, it is the civil time, or the time that a user would see on a watch or calendar.
You can see more details about DATETIME and TIMESTAMP in Data Types doc

SQL Oracle Unix timestamp conversion

I have two queries which give me different results, can someone explain why this is happening?
The first query uses the unixtime 1533624035000 which represents "07.08.2018 08:40:35" (UTC+2)
select floor((Buchungsdatum - 1533624035000) / (1000*60*60*24)) as Tag,
s.Kurztext as Buchungsstatus,
count(*) as Anzahl
from PfdBuchung b, Schluesselbegriff s
where b.Buchungsdatum >= 1533624035000 and b.SHKennung = 'H' and
b.Buchungsstatus=s.Begriff and s.Oberbegriff='Buchungsstatus' and
b.rzMandant = s.rzMandant
group by floor((Buchungsdatum - 1533624035000) / (1000*60*60*24)), s.Kurztext
order by 1,2`
Result
0 verarbeitet 21800
1 verarbeitet 23380
i have just posted the first two results here
In the 2nd query I convert the unixtimestamp to a datetime with the function POSIX_TO_TIMESTAMP which simple converts my unixts to
l_ora_timestamp := to_timestamp( '1970-01-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS' ) + numtodsinterval( (ptime/1000), 'SECOND' )
select TO_CHAR(POSIX_TO_TIMESTAMP(b.Buchungsdatum), 'YYYY-MM-DD') as Tag,
s.Kurztext as Buchungsstatus, count(*) as Anzahl
from PfdBuchung b, Schluesselbegriff s
where TO_CHAR(POSIX_TO_TIMESTAMP(b.Buchungsdatum), 'YYYY-MM-DD') >= '2018-08-07' and
b.SHKennung = 'H' and
b.Buchungsstatus = s.Begriff and
s.Oberbegriff = 'Buchungsstatus' and
b.rzMandant = s.rzMandant
group by TO_CHAR(POSIX_TO_TIMESTAMP(b.Buchungsdatum), 'YYYY-MM-DD'), s.Kurztext
order by 1,2
Result:
2018-08-07 verarbeitet 15553
2018-08-08 verarbeitet 23315
The reason is pretty obvious.
Both queries count rows where the UNIX timestamp is after 06:40:35 UTC on 7 August 2018.
The first query groups into windows of 24 hours each FROM THIS POINT IN TIME. That is, the first row in the output counts input rows from 06:40:35 on 7 August till same time on 8 August, etc.
The second query counts rows grouped by CALENDAR days (UTC), from midnight to midnight.
There is no reason for the counts to match.
In the second query, you count rows for 7 August, but only input rows with timestamp after 06:40:35 are selected - this is why you only get a count of about 15k, vs. the ~20k for all (full!) 24 hour windows.
And this has nothing to do with time zone. You may be in UTC+2 yourself, but I don't see where in your calculations there is ANY regard paid to timezone.
Your function POSIX_TO_TIMESTAMP will be wrong in winter season due to daylight saving time. Better use
l_ora_timestamp := (timestamp '1970-01-01 00:00:00 UTC' + numtodsinterval(ptime/1000, 'SECOND')) AT TIME ZONE 'Europe/Berlin';

SQL to subtract 30 mins from current time and output time should be military format 153010 only time part

SQL to subtract 30 mins from current time and output time should be military format 153010 only time part
In Oracle you can do this with:
SELECT TO_CHAR(SYSDATE - 1 / 24 / 2, 'HH24MISS') FROM DUAL
Adding 1 to a date would increase by a date, 1/24 by an hour, and 1/24/2 by 30 min.
Please note that SYSDATE will give you the time of the server which would normally by UTC. If you want the local time you have to CURRENT_DATE.