How to convert a column in seconds to dateformat in Teradata? - date

I have a column which is of bigint datatype(in seconds) which should be added to a date, so i need to convert this column into dateformat.

The arithmetic must be done against a timestamp data type in Teradata. The date data type does not have a time element associated with it. The following SQL should help point you in the right direction:
SELECT CAST(CAST(1234 AS BIGINT) AS INTERVAL SECOND(4)) AS Seconds_
, CURRENT_TIMESTAMP(0) AS CurrentTimestamp_
, CURRENT_TIMESTAMP + Seconds_ AS NewTimeStamp

If the number of seconds is less than 864000000 you can simply use interval arithmetic:
CAST(col AS TIMESTAMP) + (bigintcol * INTERVAL '0000 00:00:01' DAY TO SECOND)
Based on your other question your input is a Unixtime, those are two functions for converting them from/to Teradata timestamps:
/**********
Converting Unix/POSIX time to a Timestamp
Unix time: Number of seconds since 1970-01-01 00:00:00 UTC not counting leap seconds (currently 24 in 2011)
Also working for negative numbers.
The maximum range of Timestamps is based on the range of INTEGERs:
1901-12-13 20:45:52 (-2147483648) to 2038-01-19 03:14:07 (2147483647)
Can be changed to use BIGINT instead of INTEGER
20101211 initial version - Dieter Noeth
**********/
REPLACE FUNCTION UnixTime_to_TimeStamp (UnixTime INT)
RETURNS TimeStamp(0)
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
SQL SECURITY DEFINER
COLLATION INVOKER
INLINE TYPE 1
RETURN
CAST(DATE '1970-01-01' + (UnixTime / 86400) AS TIMESTAMP(0))
+ ((UnixTime MOD 86400) * INTERVAL '00:00:01' HOUR TO SECOND)
;
SELECT
UnixTime_to_TimeStamp(-2147483648)
,UnixTime_to_TimeStamp(0)
,UnixTime_to_TimeStamp(2147483647)
;
/**********
Converting a Timestamp to Unix/POSIX time
Unix time: Number of seconds since 1970-01-01 00:00:00 UTC not counting leap seconds (currently 24 in 2011)
The maximum range of Timestamps is based on the range of INTEGERs:
1901-12-13 20:45:52 (-2147483648) to 2038-01-19 03:14:07 (2147483647)
Can be changed to use BIGINT instead of INTEGER
20101211 initial version - Dieter Noeth
**********/
REPLACE FUNCTION TimeStamp_to_UnixTime (ts TimeStamp(6))
RETURNS INTEGER
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
SQL SECURITY DEFINER
COLLATION INVOKER
INLINE TYPE 1
RETURN
(CAST(ts AS DATE) - DATE '1970-01-01') * 86400
+ (EXTRACT(HOUR FROM ts) * 3600)
+ (EXTRACT(MINUTE FROM ts) * 60)
+ (EXTRACT(SECOND FROM ts))
;
SELECT
TimeStamp_to_UnixTime(TIMESTAMP '1901-12-13 20:45:52')
,TimeStamp_to_UnixTime(CURRENT_TIMESTAMP)
,TimeStamp_to_UnixTime(TIMESTAMP '2038-01-19 03:14:07')
;

Related

PostgreSQL query for elapsed interval

I am trying to query PostgreSQL database for rows where interval has elapsed from the last run. Main columns for this purpose are processed_at as timestamptz and frequency (in minutes) as integer.
I am failing with operators, since not many of them can operate together timestamp & integer.
Can someone please propose a query that would solve this? Thank you very much for help
From here Date/time operators:
timestamp + interval → timestamp
Add an interval to a timestamp
timestamp '2001-09-28 01:00' + interval '23 hours' → 2001-09-29 00:00:00
select now() + (10::varchar || ' min')::interval;
?column?
-------------------------------
2021-10-15 09:05:37.927163-07
--Or in your case. If I'm following you are adding the interval.
select processed_at + (frequency::varchar || ' min')::interval;
The query takes the integer value of minutes and converts it to an interval of minutes that can be added to the timestamp.
Further explanation, || is the Postgres concatenation operator and ::varchar, ::interval are casting shorthand.
UPDATE
I keep forgetting about the make_*() functions for date/time/interval
--A shorter version
select processed_at + make_interval(mins => frequency);
Saves all the casting.

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.

hour() function of excel in postgres (equivalent)

I am working recently with postgres and I have to make several calculations. However I have not been able to imitate the HOUR () function of Excel, I read the official information but it did not help me much.
The function receives a decimal and obtains the hour, minutes and seconds of the same, example the decimal 0,99988426 returns 11:59:50. Try doing this in postgres (i use PostgreSQL 10.4) with the to_timestamp function: select to_char (to_timestamp (0.99988426), 'HH24: MI: SS'); this return 19:00:00. Surely I am omitting something, some idea of how to solve this?
24:00:00 or 86400 seconds = 1
Half day(12:00 noon) or 43200 seconds = 43200/86400 = 0.5
11:59:50 or 86390 seconds = 86390/86400 = 0.99988426
So to convert your decimal value to time, all you have to do is multiply it with 86400 which will give you seconds and convert it to your format in following ways:
SELECT TO_CHAR((0.99988426 * 86400) * '1 second'::interval, 'HH24:MI:SS');
SELECT (0.99988426 * 86400) * interval '1 sec';
There are two major differences to handle:
Excel does not consider the time zone. The serial date 0 starts at 0h00, but Postgres uses the time zone so it becomes 19h. You would need to use UTC in Postgres result to have the same as in Excel.
select to_char (to_timestamp (0), 'HH24: MI: SS'),to_char (to_timestamp (0) AT TIME ZONE 'UTC', 'HH24: MI: SS');
to_char | to_char
------------+------------
19: 00: 00 | 00: 00: 00
Excel considers that 1 is one day, while Postgres considers 1 as 1 second. To get the same behavior, multiply your number by the 86400, i.e. the number of seconds in a day
select to_char (to_timestamp (0.99988426*86400) AT TIME ZONE 'UTC', 'HH24: MI: SS');
to_char
------------
23: 59: 50
(1 row)

PostgreSQL difference between two dates and return in hours and minutes

Hello I want to return in my PostgreSQL the difference between two dates:
START: 2016-06-01 00:00:00
END: 2016-06-06 08:35:33
Expected return value: 128:35:33, formatted like format [h]:mm:ss;# in Excel. Hours must be added up if there is more than 24 hours of difference.
Here's my SQL:
SELECT EXTRACT(EPOCH FROM dt_termino::timestamp - dt_inicio::timestamp)/3600 FROM crm.task_interacao WHERE id_task_tarefa = 1
UPDATE!!!
hello now i'm facing another problema I have a table like this:
my table in database like this
start;end
2013-06-01 09:29:33;2016-06-07 14:08:19
2016-06-07 14:22:09;2016-06-07 14:22:43
2016-06-07 14:22:51; null
i need to sum values ....i'm trying as you said (1st awnser).. I cant use function because i'm using inside a php code
SELECT SUM(COALESCE(end::timestamp, now()::timestamp) - start::timestamp) FROM crm.task_interacao WHERE id_task_tarefa = 1
but is returning
1102 days 26:07:54.864879
why 26 hours??? I was supose be te at maximum 24...
no problem now to return (Days HH:MM:SS) and not miliseconds
You can simply subtract timestamps to get interval:
select '2016-06-06 08:35:33'::timestamp- '2016-06-01 00:00:00' result
result
-----------------
5 days 08:35:33
(1 row)
There is no standard function to convert the result to the format you need but you can write one:
create or replace function interval_without_days(interval)
returns interval language sql as $$
select $1- date_part('day', $1)* '1d'::interval+ date_part('day', $1)* '24h'::interval;
$$;
select interval_without_days('2016-06-06 08:35:33'::timestamp- '2016-06-01 00:00:00');
interval_without_days
-----------------------
128:35:33
(1 row)
Question #2. Use the functions date_trunc(text, interval) and justify_hours(interval):
select date_trunc('sec', justify_hours('1102 days 26:07:54.864879'));
date_trunc
--------------------
1103 days 02:07:54
(1 row)

How to write bigint (timestamp in milliseconds) value as timestamp in postgresql

I'm trying to store in timestamp with timezone field my value. It is in milliseconds from 1970.
select TO_CHAR(TO_TIMESTAMP(1401432881230), 'DD/MM/YYYY HH24:MI:SS.MS')
Expected 30/5/2014 11:29:42 10:54:41.230, but get
22/08/46379 23:27:02.000
Unix timestamps measures time with seconds, and not milliseconds (almost everywhere, in PostgreSQL too).
Therefore you need to call
SELECT TO_TIMESTAMP(1401432881230 / 1000);
If you want to preserve milliseconds, call with double precision:
SELECT TO_TIMESTAMP(1401432881230::double precision / 1000);
This is how I convert ms to timestamp and keep ms instead seconds.The accepted answer will drop ms.
WITH ts AS (SELECT 1401432881230 AS ts)
SELECT to_timestamp(ts / 1000) + ((ts % 1000 ) || ' milliseconds') :: INTERVAL
FROM ts;
-- FOR ALTER COLUMN
ALTER TABLE my_info
ALTER COLUMN tstmp TYPE TIMESTAMP USING to_timestamp(tstmp / 1000) + ((tstmp % 1000) || ' milliseconds') :: INTERVAL;
Okay, I understood. My INSERT should looks like:
INSERT INTO events (timestamp) VALUES (to_timestamp(TO_CHAR(TO_TIMESTAMP(1401432881222 / 1000), 'YYYY-MM-DD HH24:MI:SS') || '.' || (1401432881222%1000), 'YYYY-MM-DD HH24:MI:SS.MS'))
I'm converting bigint-timestamp with milliseconds to text with required format ('YYYY-MM-DD HH24:MI:SS.MS') and pass it to to_timestamp function.