How can I have timestamp displayed in UTC+02 (same timezone) for both the queries below? - postgresql

My first query is:
SELECT distinct wfc_request_job_id,wfc_request_job_info,
replace(iso_cc,';',' ') as "iso_cc",to_char(wfc_request_start_ts,'yyyy-MM-dd HH:mm:ss') as ts,
sent_message_count,
(link_object_count + poi_object_count + point_address_object_count) as request_object_count
FROM wfc_request_job
where
wfc_request_job_id=173526;
This returns ts as 2015-08-16 03:08:59
Second Query:
SELECT wfc_request_job_id,wfc_request_start_ts,wfc_request_end_ts,replace(iso_cc,';',' ') as "iso_ccs",sent_message_count,wfc_queue_name
FROM wfc_request_job
where
to_char(wfc_request_start_ts,'YYYY-MM-DD') >= to_char(to_date('08/16/2015','MM/DD/YYYY'),'YYYY-MM-DD')
and to_char(wfc_request_start_ts,'YYYY-MM-DD') <= to_char(to_date('08/16/2015','MM/DD/YYYY'),'YYYY-MM-DD')
order by wfc_request_job_id desc
This returns ts of the job id mentioned above as - "2015-08-16 15:58:59.809+02"
How can I make both the queries return ts in UTC+02 - i.e. same timezone
The data type of wfc_request_start_ts is - timestamp with timezone
I changed to queries to have the format HH24:MI:SS however that did not help. Please note that the webapp using these queries will be opened in both Germany and USA.

According to postgresql manual to_char there is TZ (and OF as of v9.4) template patterns for Date/Time formatting.
Therefore in query you need to add it so
postgres=# select to_char(now(),'yyyy-MM-dd HH24:mm:ss TZ');
to_char
------------------------
2015-08-19 12:08:56 CEST
(1 row)
Also, make sure you specify timezone when converting
so instead
to_date('08/16/2015','MM/DD/YYYY')
use
TIMESTAMP WITH TIME ZONE '2015-08-16 00:00:00+02';
in second query.

Related

Recurring future date at every 3 month after create date in PostgreSQL

I am looking for a function in PostgreSQL which help me to generate recurring date after every 90 days from created date
for example: here is a demo table of mine.
id date name
1 "2020-09-08" "abc"
2 "2020-09-08" "xyz"
3 "2020-09-08" "def"
I need furure date like 2020-12-08, 2021-03-08, 2021-06-08, and so on
First it's important to note that, if you happen to have a date represented as text, then you can convert it to a date via:
SELECT TO_DATE('2017-01-03','YYYY-MM-DD');
So, if you happen to have a text as an input, then you will need to convert it to date. Next, you need to know that if you have a date, you can add days to it, like
SELECT CURRENT_DATE + INTERVAL '90 day';
Now, you need to understand that you can use dynamic variables, like:
select now() + interval '1 day' * 180;
Finally, you will need a temporary table to generate several values described as above. Read more here: How to return temp table result in postgresql function
Summary:
create a function
that generates a temporary table
where you insert as many records as you like
having the date shifted
and converting text to date if needed
You can create a function that returns a SETOF dates/timestamps. The below function takes 3 parameters: a timestamp, an interval, the num_of_periods desired. It returns num_of_periods + 1 timestamps, as it returns the original timestamp and the num_of_periods each the specified interval apart.
create or replace
function generate_periodic_time_intervals
( start_date timestamp
, period_length interval
, num_of_periods integer
, out gen_timestamp timestamp
)
returns setof timestamp
language sql
immutable strict
as $$
select (start_date + n * period_length)::timestamp
from generate_series(0,num_of_periods) gs(n)
$$;
For your particular case to timestamp/date as necessary. The same function would work for your case with the interval specified as '3 months' or of '90 days'. Just a note the interval specified can be any valid INTERVAL data type. See here. It also demonstrates the difference between 3 months and 90 days.

How do I go from Varchar string into Unix time type? Greenplum

I'm fairly inexperienced with SQL let alone PostgreSQL so appreciate your help.
Let's say we have a varchar column called ID that is a combination of IP address and a unix epoch time string.
So when I run this query:
SELECT substring(b.id from char_length (r.IP_address)+2 for 10), b.id, r.ip_address
FROM bq b
INNER JOIN event r ON r.visitor_id::TEXT = b.id::TEXT
LIMIT 3;
Output
substring id ip_address
1460854333 97.128.39.256.1460854333288493 97.128.39.256
So the output of the substring is a unix time stamp but it is in a varchar format. How do I convert the varchar into a unix timestamp? Ultimately I am going to convert that time stamp into date I just don't think I can directly go from the varchar of a unix string to a date?
As Terra said, use the to_timestamp() function:
# select to_timestamp('1460854333') ;
to_timestamp
------------------------
2016-04-16 17:52:13-07
(1 row)
If a date is the type you're after, just add the ::date cast:
# select to_timestamp('1460854333')::date ;
to_timestamp
------------------------
2016-04-16
(1 row)
The function is basically executing this:
select ('epoch'::timestamptz + '1460854333'::float * '1 second'::interval) ;

Postgres Time Difference

I am trying to retrieve time difference in minutes from a table(login_history as t1) using postgresql .
When i tried this code
((date_part('hour', timestamp '2014-04-25 09:44:21')- date_part('hour', timestamp '2014-04-25 08:32:21'))*60 +(date_part('minutes', timestamp '2014-04-25 09:44:21')- date_part('minutes', timestamp '2014-04-25 08:32:21'))) as TimeNew
It works fine.
But when i tried to retrieve information from a table t1 using this code
((date_part('hour', timestamp t1.login_date)- date_part('hour', timestamp t1.logout_date))*60 +
(date_part('minutes', timestamp t1.login_date)- date_part('minutes', timestamp t1.logout_date))
) as TimeNew
It throws this error
SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "t1"
Thanks
I would use the interval that results from subtracting two timestamps for a much simpler expression:
select extract (epoch from (timestamp '2014-04-25 09:44:21' - timestamp '2014-04-25 08:32:21'))::integer/60
(gives 72)
or for your table:
select extract (epoch from (t1.logout_date - t1.login_date))::integer/60
If you need to cast:
select extract (epoch from (t1.logout_date::timestamp - t1.login_date::timestamp))::integer/60
or see the to_timestamp function for custom string parsing: http://www.postgresql.org/docs/9.4/static/functions-formatting.html
I needed to remove the timestamp from the query before t1 and the query works.

to_char returning wrong date postgresql

So in my database i have a table with startimestamp that is "Timestamp with time zone" type
but what i want to display the timestamp without the time zone so i thought this would work
Select to_char("StartTimestamp",'YYYY/MM/DD HH24:MM:SS')from "Samples" where "ID" = 20
and a i get
"2013/08/02 14:08:04"
but the when i do it without the to_char and just call the timestamp for the same id like this
select "StartTimestamp" from "Samples" where "ID"=20
i get this which is the correct one
"2013-08-02 14:31:04-07"
I'm i missing something the to_char statement? Thanks
Change MM to MI in the minutes place
select
to_char(now(),'YYYY/MM/DD HH24:MM:SS'),
to_char(now(),'YYYY/MM/DD HH24:MI:SS');
to_char | to_char
---------------------+---------------------
2013/08/21 15:08:00 | 2013/08/21 15:51:00

Postgresql Query very slow with ::date, ::time, and interval

I have a sql query that is very slow:
select number1 from mytable
where symbol = 25
and timeframe = 1
and date::date = '2008-02-05'
and date::time='10:40:00' + INTERVAL '30 minutes'
The goal is to return one value, and postgresql takes 1.7 seconds to return the desired value(always a single value). I need to execute hundreds of those queries for one task, so this gets extremely slow.
Executing the same query, but pointing to the time directly without using interval and ::date, ::time takes only 17ms:
select number1 from mytable
where symbol = 25
and timeframe = 1
and date = '2008-02-05 11:10:00'
I thought it would be faster if I would not use ::date and ::time, but when I execute a query like:
select number1 from mytable
where symbol = 25
and timeframe = 1
and date = '2008-02-05 10:40:00' + interval '30 minutes'
I get a sql error (22007). I've experimented with different variations but I couldn't get interval to work without using ::date and ::time. Date/Time Functions on postgresql.org didn't help me out.
The table got a multi column index on symbol, timeframe, date.
Is there a fast way to execute the query with adding time, or a working syntax with interval where I do not have to use ::date and ::time? Or do I need to have a special index when using queries like these?
Postgresql version is 9.2.
Edit:
The format of the table is:
date = timestamp with time zone,
symbol, timeframe = numeric.
Edit 2:
Using
select open from ohlc_dukascopy_bid
where symbol = 25
and timeframe = 1
and date = timestamp '2008-02-05 10:40:00' + interval '30' minute
Explain shows:
"Index Scan using mcbidindex on mytable (cost=0.00..116.03 rows=1 width=7)"
" Index Cond: ((symbol = 25) AND (timeframe = 1) AND (date = '2008-02-05 11:10:00'::timestamp without time zone))"
Time is now considerably faster: 86ms on first run.
The first version will not use a (regular) index on the column named date.
You didn't provide much information, but assuming the column named date has the datatype timestamp (and not date), then the following should work:
and date = timestamp '2008-02-05 10:40:00' + interval '30 minutes'
this should use an index on the column named date (but only if it is in fact a timestamp not a date). It is essentially the same as yours, the only difference is the explicit timestamp literal (although Postgres should understand '2008-02-05 10:40:00' as a timestamp literal as well).
You will need to run an explain to find out if it's using an index.
And please: change the name of that column. It's bad practise to use a reserved word as an identifier, and it's a really horrible name, which doesn't say anything about what kind of information is stored in the column. Is it the "start date", the "end date", the "due date", ...?