Convert date from long time postgres - sql

How do I select the date as a readable string from epoch time in milliseconds?
Some like: SELECT *, to_date(time_in_milli_sec) FROM mytable

Per PostgreSQL docs:
SELECT *, to_timestamp(time_in_milli_sec / 1000) FROM mytable

SELECT timestamp 'epoch' + time_in_millisec * interval '1 ms'
FROM mytable;
See the manual here.

For milliseconds
SELECT timestamp 'epoch' + proyecto.fecha_inicio * interval '1 ms'
from proyecto.proyecto
where proyecto.fecha_inicio is not null
For seconds
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720 * INTERVAL '1 second';
In the manual : http://www.postgresql.org/docs/current/interactive/functions-datetime.html.
Line: .. "Here is how you can convert an epoch value back to a time stamp"..

Original question was related to Date data type, but all the answers so far relate to Timestamp data type.
One way to convert milliseconds to Date would be:
SELECT DATE(any_time_field_containing_milliseconds/ 1000) FROM mytable;
This seems to use the timezone defined for database

Related

Oracle: Error in converting DateTime to Epoch

While trying to convert datetime to epoch, I am getting an error: ORA-01810: format code appears twice
QracleSQL query:
select (trunc(TO_TIMESTAMP('2022-05-08T19:09:17Z', 'yyyy-MM-dd"T"HH:mm:ssXXX')) - TO_DATE('01/01/1970', 'MM/DD/YYYY')) * 24 * 60 * 60 from dual;
You should use:
TO_TIMESTAMP_TZ instead of TO_TIMESTAMP
the format model YYYY-MM-DD"T"HH24:MI:SS.FF TZD rather than incorrectly using MM twice, HH24 instead of HH, .FF instead of XXX, and TZD instead of hardcoding "Z".
Make sure you always convert your timestamp to UTC time zone (yours is already but others may not be)
Don't TRUNCate the timestamp to a DATE at midnight or you will lose the time component.
Like this:
SELECT ROUND(
(
TRUNC(timestamp_value AT TIME ZONE 'UTC', 'MI')
- DATE '1970-01-01'
) * 86400
+ EXTRACT(SECOND FROM timestamp_value AT TIME ZONE 'UTC')
) AS epoch_time
FROM (
SELECT TO_TIMESTAMP_TZ(
'2022-05-08T19:09:17Z',
'YYYY-MM-DD"T"HH24:MI:SS.FF TZD'
) AS timestamp_value
FROM DUAL
);
Which outputs:
EPOCH_TIME
1652033357
db<>fiddle here
Something like this:
TEST DATA
create table sample_inputs (ts_string) as
select '2022-05-08T16:49:34Z' from dual union all
select '2022-04-15T04:20:13.525Z' from dual
;
QUERY AND OUTPUT
with
prep (ts_string, ts) as (
select ts_string,
to_timestamp(ts_string, 'yyyy-mm-dd"T"hh24:mi:ss.ff"Z"')
from sample_inputs
)
select ts_string,
round((trunc(ts, 'mi') - date '1970-01-01') * 24 * 3600)
+ extract(second from ts)
as epoch
from prep;
TS_STRING EPOCH
-------------------------- -----------
2022-05-08T16:49:34Z 1652028574
2022-04-15T04:20:13.525Z 1649996413.525
NOTES
In your attempt there are several mistakes. The Oracle fractional-seconds element is ff, not xxx. You are missing the placeholder for the hard-coded Z at the end (you have "T" in your mask, which is correct, but you are missing the similar "Z"). HH is insufficient - it must be either HH24 or HH followed by AM (or equivalently PM) at the end. In your example, it is obviously HH24. And MM and mm mean the same thing in Oracle - this is not Unix. The element for minutes is mi or equivalently MI.
The query I wrote preserves fractional seconds in the epoch. Another question earlier today (perhaps yours too, under another user name) was closed as being a "duplicate" - but the claimed "duplicate" has absolutely nothing about preserving fractional seconds, when the input is an Oracle timestamp vs an Oracle date (which always does have a time component, but only in whole seconds).

Between two Unix dates in Oracle

Thanks to previous question...
I have a more simplified OR statement.
Question is instead of a IN how could I change this to a between?
TO_DATE(TO_CHAR(TO_DATE(''19700101'',''yyyymmdd'') + + (FLOOR(ph.change_date/24/60/60)))) IN (''23-DEC-2020'', ''29-DEC-2020'')
So I want to say between the 23-DEC-2020 and 29-DEC-2020 including both?
Thanks
If you want to use an index on the change_date column then perform the conversion on the literal values and convert them to epoch times (rather than converting the column's epoch time to a date, which would not allow you to use a normal index on the column):
ph.change_date BETWEEN ( DATE '2020-12-23' - DATE '1970-01-01' ) * 86400
AND ( DATE '2020-12-29' - DATE '1970-01-01' ) * 86400 + 86399
change_date seems to be in Unix timestamp format -- the number of seconds since 1970-01-01. I would recommend doing the comparison by converting constant values to the same format:
where ph.change_date >= (date '2020-12-23' - date '1970-01-01') * 24 * 60 * 60 and
ph.change_date < (date '2020-12-30' - date '1970-01-01') * 24 * 60 * 60
Note that this is index (and partition) friendly. And, the second comparison is < on the next day to get the entire day.
If you need to deal with the column as "real" dates, you can add a computed column
alter table t add column change_date_date date generated always as
(cast(date '1970-01-01' as timestamp) + change_date * interval '1' second);
You can then reference change_date_date and even define a an index on it.
You can do it with the between keyword.
For example:
to_date('2021.01.06', 'yyyy.mm.dd') between to_date('2021.01.01', 'yyyy.mm.dd') and to_date('2021.01.31', 'yyyy.mm.dd')
I think we can try like this
where <expression>
between TO_DATE('23-DEC-2020','DD-MON-YYYY') and
TO_DATE('29-DEC-2020','DD-MON-YYYY')
You can convert the epoch time(ph.change_date) to date and then compare as follows:
Date'1970-01-01' + FLOOR(ph.change_date/24/60/60) -- considering that change_date is epoch time
between date'2020-12-23' and date'2020-12-23'

postgres convert a substring to epoch

I'm trying to convert a epoch timestamp to a human readable timestamp in a single query but I'm getting a little stuck - any help is appreciated.
testing=# SELECT creation_time FROM users LIMIT 1;
creation_time
---------------
1354006445722
(1 row)
testing=# SELECT SUBSTRING('1498123813330', 1,10);
SUBSTRING
------------
1498123813
(1 row)
testing=# SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 1498123813 * INTERVAL '1 second';
?column?
------------------------
2017-06-22 02:30:13-07
(1 row)
Anyway to put this into a single query?
What you want is CASTing, i.e.
SELECT TIMESTAMP WITH TIME ZONE 'epoch' +
SUBSTRING(creation_time, 1, 10)::NUMERIC * INTERVAL '1 second';
But, if creating time is epoch milliseconds, you could do:
SELECT to_timestamp(creation_time::double precision / 1000)
instead, which will preserve milliseconds too. You can print timestamp out with to_char if you want a format, other than the default timestamp output.
http://rextester.com/EHPNJ86308
Assuming created_time is stored as a varchar, you can apply the same substring logic to it and cast it to a number:
SELECT TIMESTAMP WITH TIME ZONE 'epoch' +
SUBSTRING(creation_time, 1,10)::NUMERIC * INTERVAL '1 second'
FROM users

How do I get the unix epoch from Oracle date? [duplicate]

This question already has answers here:
Convert from date to epoch-Oracle
(3 answers)
Closed 10 months ago.
Does anyone have a better AND faster solution on getting the unix epoch timestamp using Oracle SQL than this?:
SQL> select (cast(sysdate as date) - cast(to_date('1970-01-01', 'YYYY-MM-DD') as date)) * 86400 as unixepoch from dual;
UNIXEPOCH
----------
1490789604;
Oneliner preferred ;)
The above answer is only correct if your database time zone is in UTC. Unix time is always in UTC.
The correct answer that works on any database, regardless of configuration is:
--Convert current time to epoch.
select (cast (systimestamp at time zone 'UTC' as date) - date '1970-01-01') * 86400
from dual
--Convert hard-coded timestamp to epoch.
select (cast (timestamp '2019-12-31 23:59:59' at time zone 'UTC' as date) - date '1970-01-01') * 86400
from dual;
You do not need to cast the values as dates, since they are already dates.
SELECT ( SYSDATE - DATE '1970-01-01' ) * 86400 AS unixepoch
FROM DUAL;

extracting year from unix time in PostgreSQL

I have a Log table and this is it's description:
user_id(bigint)
time (bigint)
My question is, how can I extract the year from the time column in PostgreSQL?
This works in MySQL:
SELECT l.user_id, year(from_unixtime(l.time))
FROM log l;
select date_part('year', to_timestamp(1365682413));
to_timestamp is our friend here and has taken a unix time since at least version 8.1.
select extract(year from timestamp 'epoch' + "time" * interval '1 second')
from log;