Convert seconds (string) to timestamp in Impala - type-conversion

I have 2 columns: end_time and seconds
end_time is stored as a unix_timestamp and seconds is stored as a string. I need to subtract the end_time column from the seconds column to get a new column (i.e. start_time)
I'm having a hard time with this as I don't think Impala supports CONVERT() or DATEADD() for me to convert seconds to a timestamp, then to subtract it from end_time. Any suggestions on how to do this in Impala?
Example:
end_time seconds
2020-09-02 21:12:34 65
Desired outcome:
start_time
2020-09-02 21:11:29
EDIT
Progress so far:
CAST(CONCAT(CAST(from_timestamp(CAST(end_time AS TIMESTAMP),'yyyy-MM-dd') AS STRING), ' ', CAST(to_timestamp(from_timestamp(CAST(seconds AS TIMESTAMP),'HH:mm:ss'),'HH:mm:ss') AS STRING)) as TIMESTAMP) AS updated_time
The above gives me the seconds column in a TIMESTAMP format with the yyyy-MM-dd of the end_time.
How can I now subtract end_time and updated_time without messing up the dates?
E.g. I don't want to subtract 2021-01-01 from 2021-01-01. I want the time difference to come from the HH:mm:ss, not the yyyy-MM-dd

Actually a quick and simple solution in the end:
to_timestamp(end_time, 'yyyy-MM-dd HH:mm:ss') end_time
CAST(table.seconds AS INT) sec
date_sub(end_time, INTERVAL sec seconds) start_time

Related

Postgresql timestamp difference greater than 1 hour

Hi I have a entrytime and exittime timestamp in my database, how can I query it to display only ones where the person exited more than an hour later;
Select * from store where EXTRACT(EPOCH FROM (exittime - entrytime))/3600 >60
That's what I have so far but it won't work, any help would be appreciated.
Just subtract the values and compare it with an interval
Select *
from store
where exittime - entrytime > interval '1 hour';
This assumes that both columns are defined as timestamptz or timestamp

How to cast an int of microseconds into a interval field in postgres?

There is this question about how to extract microseconds from an interval field
I want to do the opposite, I want to create an interval from a numeric microseconds. How would I do this?
The reason is I want to take a table of this format
column_name | data_type
-------------+--------------------------
id | bigint
date | date
duration | numeric
and import it into a table like this
column_name | data_type
-------------+--------------------------
id | integer
date | date
duration | interval
Currently I am trying:
select CAST(duration AS interval) from boboon.entries_entry;
which gives me:
ERROR: cannot cast type numeric to interval
LINE 1: select CAST(duration AS interval) from boboon.entries_entry;
You can do:
select duration * interval '1 microsecond'
This is how you convert any date part to an interval in Postgres. Postgres supports microseconds, as well as more common units.
you can append the units and then cast to interval
example:
select (123.1234 || ' seconds')::interval
outputs:
00:02:12.1234
valid units are the following (and their plural forms):
microsecond
millisecond
second
minute
hour
day
week
month
quarter
year
decade
century
millennium

Postgresql: How to find hours between 2 dates and 2 times?

Postgresql 9.1
I'm trying to use a query to find the difference, in fractional/decimal hours, between 2 dates and 2 times for a timesheet system. I'm using the query to make sure the software (not written by me) doesn't have any bugs. Here are the fields in the table I'm using: startdate is a Date field, starttime is a Time field, enddate is a Date field, endtime is a Time field.
I've looked at the date time docs for 9.1 and still haven't found what I need.
age() takes 2 timestamps and appears to give a difference in integer, not fractional, days. I don't think it's possible to multiply the result of age() by 24 to get hours. Nor do I know how to include the time in the age() function.
I could not find out to convert a date and time to some thing else to use another function.
I have searched Google and Stackoverflow and have not found info to help me. I've been spending about 4 weeks on this off and on. So probably 30 hours already.
NOTE: I don't think I can add user-defined functions. I don't have the permissions.
Example data:
Startdate and time: '2016-04-29' and '23:00:00'
Enddate and time: '2016-04-30' and '01:30:00'
I've also tried this sql statement.
SELECT employeetime.dcmasterid as empid,
nonchargeabletime.startdate as ncsdate,
nonchargeabletime.starttime as ncstime,
nonchargeabletime.enddate as ncedate,
nonchargeabletime.endtime as ncetime,
employeetime.dchours as normhrs,
(timestamp (startdate || ' ' || starttime) - timestamp (enddate || ' ' || endtime)) as diffhrs
FROM employeetime, nonchargeabletime
WHERE (nonchargeabletime.employeetime=employeetime.dcautoinc)
AND (nonchargeabletime.startdate >= '2016-04-24')
AND (nonchargeabletime.startdate <= '2016-04-30')
AND (employeetime.dcmasterid IN ('BLURG'))
AND (nonchargeabletime.nonchargeabletype=10)
ORDER BY employeetime.dcmasterid, nonchargeabletime.startdate, nonchargeabletime.starttime;
But I get a syntax error at startdate where it says (timestamp (startdate ||.
Anyone have any clues how to do this?
Thank you.
Adding a time to a date yields a timestamp and subtracting one timestamp from another returns an interval.
So all you need to do is:
(enddate + endtime) - (startdate + starttime) as diff
An interval is nice in the context of SQL, but usually harder to handle in a programming language. You can easily convert an interval to seconds using extract(epoch from interval)
If you want to convert that to hours use extract and divide by 3600
extract(epoch from (enddate + endtime) - (startdate + starttime))/3600 as diff_hours
Since you don't have strings, you can't use || operator, but you can just add time to date (http://www.postgresql.org/docs/9.1/static/functions-datetime.html).
This should work (you can floor result if you want integer hours):
postgres=# create temporary table ts (startdate date, starttime time, enddate date, endtime time);
CREATE TABLE
postgres=# insert into ts values('2016-05-03', '11:45:15', '2016-05-04', '13:55:43');
INSERT 0 1
postgres=# SELECT startdate,starttime,enddate,endtime, (enddate+endtime)-(startdate+starttime) as interval from ts;
startdate | starttime | enddate | endtime | interval
------------+-----------+------------+----------+----------------
2016-05-03 | 11:45:15 | 2016-05-04 | 13:55:43 | 1 day 02:10:28
(1 row)
postgres=# SELECT startdate,starttime,enddate,endtime, EXTRACT(epoch FROM ((enddate+endtime)-(startdate+starttime)))/3600 as hours from ts;
startdate | starttime | enddate | endtime | hours
------------+-----------+------------+----------+------------------
2016-05-03 | 11:45:15 | 2016-05-04 | 13:55:43 | 26.1744444444444
(1 row)
WITH zooi(startdate,starttime, enddate,endtime) AS (
VALUES('2016-04-29'::date , '23:00:00'::time
,'2016-04-30'::date , '01:30:00'::time )
)
, stamps (sta, sto) AS (
select (z.startdate+z.starttime)::timestamp
, (z.enddate+z.endtime)::timestamp
FROM zooi z
)
SELECT sta,sto
, age(sto,sta) AS how_old
, (sto-sta)::time AS diff
FROM stamps;
Next step would be to convert the time (or interval) result to days or hours.

Postgres Concate: Date + Timestamp + Integer of 7

How can I combine these two columns and add integer of 7 to it? In postgres.
Both columns are in the table a_event.
start_time is a timestamp without time zone data type.
start_date is a date data type.
so far I have:
SELECT start_time || start_date AS start_date_time
FROM a_event;
This works but it shows:
2015-03-06 21:17:162015-02-06
How can I get it to simply show:
2015-03-06 13:17:16 with an added 7 days so: 2015-03-13 in the desired result.
The || operator concatenates two strings, so the 'start_time' and 'start_date' columns are converted to text and then concatenated to give the result you see.
You want to add 7 days to the starting date. That is simply:
SELECT start_date + 7 AS start_date_time
FROM a_event;
On a date data type the + operator adds a number of days.
If you want to keep the starting time information, the solution is slightly more complex:
SELECT start_time + interval '7 days' AS start_date_time
FROM a_event;
The timestamp data type records microseconds since 01-01-1970, so you have to explicitly indicate that you want to add an interval of 7 days (and not 7 microseconds).

Ignoring seconds from timestamp postgres

I am running a cron job every 1 minute for notifying users for events
select * from events where event_start = now() - interval '30 minutes'
so that I can send the users a notification prior to 30 mins of event
problem is event start is a timestamp field so if there is a difference in seconds it this wll not work ,so how can ignore the seconds part .
You can use date_trunc() to remove the seconds:
select *
from events
where event_start = date_trunc('second', now()) - interval '30' minutes
More details in the manual: http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
In order to ignore seconds, you can use date_trunc() function.
The function date_trunc is conceptually similar to the trunc function
for numbers.
date_trunc(field, source [, time_zone ]) source is a value expression
of type timestamp, timestamp with time zone, or interval. (Values of
type date and time are cast automatically to timestamp or interval,
respectively.) field selects to which precision to truncate the input
value. The return value is likewise of type timestamp, timestamp with
time zone, or interval, and it has all fields that are less
significant than the selected one set to zero (or one, for day and
month).
Valid values for field are:
microseconds
milliseconds
second
minute
hour
day
week
month
quarter
year
decade
century
millennium
SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
Result: 2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
Result: 2001-01-01 00:00:00
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00');
Result: 2001-02-16 00:00:00-05
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00', 'Australia/Sydney');
Result: 2001-02-16 08:00:00-05
SELECT date_trunc('hour', INTERVAL '3 days 02:47:33');
Result: 3 days 02:00:00
So in your case, you should use:
SELECT *
FROM events
WHERE event_start = date_trunc('minute', now()) - INTERVAL '30' MINUTE;