Postgresql difference in time based on interval - postgresql

I have a table, time_slots, which has a column start_time. My users table has a column, hours_before (int), which is the number of hours before the start_time to receive a notification.
I'm running a job every 5 minutes that checks the time slots that have a start_time which is now + hours_before. All my datetimes are store in UTC. I can't figure out the correct where clause to get the appropriate time slots.
Right now I'm passing in the current time in UTC as a string rather than doing something like current_timestamp at time zone 'UTC'.
(extract(epoch from starts_at) - extract(epoch from (date '2020-11-09 06:20:00' + (users.hours_before * INTERVAL '1 hour')))) = 0
Here is a test query to see what the values are inside of a select. In this example, (6 * INTERVAL '1 hour') would be where users.hours_before would be. I'm using a static 6 while tinkering.
select
(extract(epoch from "starts_at") - extract(epoch from date '2020-11-09 06:20:00')) / 3600 as hours,
(extract(epoch from "starts_at") - extract(epoch from (date '2020-11-09 06:20:00' + (6 * INTERVAL '1 hour')))) as other_interval,
*
from
"time_slots"
where
"starts_at" > '2020-11-09 06:20:00'
order by hours asc;
For example, the following query has the same hours and other_interval values as the above query, despite the date being 2020-11-09 10:00:00 instead of 2020-11-09 06:00:00. Shouldn't those columns be 4 hours different since they change by 4 hours?
select
(extract(epoch from "starts_at") - extract(epoch from date '2020-11-09 10:00:00')) / 3600 as hours,
(extract(epoch from "starts_at") - extract(epoch from (date '2020-11-09 10:00:00' + (6 * INTERVAL '1 hour')))) as other_interval,
*
from
"time_slots"
where
"starts_at" >= '2020-11-09 06:00:00'
order by hours asc;

Related

Postgresql - query to get difference in data count

I have two tables, today's_table and yeterday's_table.
I need to compare the data for an interval of 15 mins at exact same times for today and yesterday.
For example, for below data let's I need to check from 00:00:00 and 00:15:00 on 20201202 and 20201202. So difference should come out as '3' since the yesterday's_table has 8 records and today's_table has 5 records.
today's_table:
Yesterday's table:
I tried something like; (consider now() is 00:15:00)
select count(*) from yeterday's_table where time between now() - interval "24 hours" and now() - interval "23 hours 45 mins"
minus
select count(*) from today's_table where time = now() - interval "15 minutes";
is there any other way to do this?
You can easily do this with subqueries:
SELECT b.c - a.c
FROM (select count(*) as c from yeterdays_table where time between now() - interval '24 hours' and now() - interval '23 hours 45 mins') a,
(select count(*) as c from todays_table where time = now() - interval '15 minutes') b;
Bear in mind you need to single-quote your intervals, and your table names cannot have quotes in them.

getting dynamic timezone offset based on month

I've a query
"TO_CHAR((TIMEZONE('#{ tz_offset }', created_at) + (#{ months.to_s } * INTERVAL '1 month')))"
The final query becomes:
"SELECT sum(price) as sum_total, min(TO_CHAR((TIMEZONE('-05:00', created_at) + (0 * INTERVAL '1 month')), 'YYYY-MM')) as formatted_date, min(TO_CHAR((TIMEZONE('-05:00', created_at) + (0 * INTERVAL '1 month')), 'Mon/YY')) as key FROM items WHERE created_at BETWEEN '2018-09-01 04:00:00' AND '2020-02-01 03:59:59' GROUP BY TO_CHAR((TIMEZONE('-05:00', created_at) + (0 * INTERVAL '1 month')), 'YYYY-MM') ORDER BY TO_CHAR((TIMEZONE('-05:00', created_at) + (0 * INTERVAL '1 month')), 'YYYY-MM')"
As you can see the tz_offset becomes -05:00
However, the problem I'm running into is that the tz_offset is static, and it can change based on the month. Such as, CST time is -05:00 in July but -06:00 in August. I would like to make sure the amounts fall into correct months based on daylight savings. Is it possible for postgres to calculate this tz_offset based on timezone?
I was able to get it to work using
created_at AT TIME ZONE <tz_name>
Rather than the offset, use the name of the time zone, for example America/Chicago. That includes the daylight savings time setting.

Last 7 days from postgres table epoch timestamp

I have a table (funny_quotes) which has a column called quote_date and it stores data in unix epoch time (seconds)
I want to run a query to only return data from this table(funny_quotes) only from the last 3 days.
I created a table locally in postgres but unable to store dates as epoch time, they only get stored as timestamp values
select * from funny_quotes where quote_date > (now() - interval '3 days')
You should modify the right side of the equation to epoch in order to be able to compare:
select * from funny_quotes where quote_date > extract(epoch from (now() - interval '3 days'))
Or the other way around: convert quote_date into timestamp:
select * from funny_quotes where to_timestamp(quote_date) > now() - interval '3 days'
You can read more about it in the docs

PostgreSQL - Difference between Current Date and a Date from Database

I'm trying to make a SELECT query which will compare current time with time at database. For example in database there is a record '2018-02-07 12:00:00' and I wanna compare it to current time. If current time is '2018-02-07 11:00:00', record '2018-02-07 12:00:00' should be visible in results. It should compare two dates and shows only those who are 1h before or after current time.'
Tried something like this:
SELECT * FROM events WHERE age(current_date, event_date) < '1 hour';
or
SELECT * FROM events WHERE event_date > (now() - INTERVAL '1 hour');
those that are 1h before or after current time
Wouldn't the logic look like this?
SELECT e.*
FROM events e
WHERE e.event_date > now() - INTERVAL '1 hour' AND
e.event_date < now() + INTERVAL '1 hour'

select dates between two unix timestamps

I have the table users.
Columns:
user_id - integer
user_date - integer(unix timestamp)
Some of rows have user_date and some have NULL.
I need to find all user_id's which user_date includes period between '2012-10-21' and '2012-10-24'
SELECT *
FROM users
WHERE user_date BETWEEN
EXTRACT(EPOCH FROM date '2012-10-21') AND
EXTRACT(EPOCH FROM date '2012-10-24' + interval '1 day');
If you don't want the end date to be included, remove the bit adding a day to that.
select *
from users
where
timestamp 'epoch' + user_date * interval '1 second' between '2012-10-21' and '2012-10-24'
and
user_date is not null