The statement gives me the date and time.
How could I modify the statement so that it returns only the date (and not the time)?
SELECT to_timestamp( TRUNC( CAST( epoch_ms AS bigint ) / 1000 ) );
You use to_timestamp function and then cast the timestamp to date
select to_timestamp(epoch_column)::date;
You can use more standard cast instead of ::
select cast(to_timestamp(epoch_column) as date);
More details:
/* Current time */
select now(); -- returns timestamp
/* Epoch from current time;
Epoch is number of seconds since 1970-01-01 00:00:00+00 */
select extract(epoch from now());
/* Get back time from epoch */
-- Option 1 - use to_timestamp function
select to_timestamp( extract(epoch from now()));
-- Option 2 - add seconds to 'epoch'
select timestamp with time zone 'epoch'
+ extract(epoch from now()) * interval '1 second';
/* Cast timestamp to date */
-- Based on Option 1
select to_timestamp(extract(epoch from now()))::date;
-- Based on Option 2
select (timestamp with time zone 'epoch'
+ extract(epoch from now()) * interval '1 second')::date;
In your case:
select to_timestamp(epoch_ms / 1000)::date;
PostgreSQL Docs
select to_timestamp(cast(epoch_ms/1000 as bigint))::date
worked for me
On Postgres 10:
SELECT to_timestamp(CAST(epoch_ms as bigint)/1000)
The solution above not working for the latest version on PostgreSQL. I found this way to convert epoch time being stored in number and int column type is on PostgreSQL 13:
SELECT TIMESTAMP 'epoch' + (<table>.field::int) * INTERVAL '1 second' as started_on from <table>;
For more detail explanation, you can see here https://www.yodiw.com/convert-epoch-time-to-timestamp-in-postgresql/#more-214
This works for me fine:
SELECT t.*,
to_timestamp(cast(t.prev_fire_time/1000 as bigint)) as prev_fire_time,
to_timestamp(cast(t.next_fire_time/1000 as bigint)) as next_fire_time,
to_timestamp(cast(t.start_time/1000 as bigint)) as start_time
FROM public.qrtz_triggers t;
Seconds since epoch with GNU date:
$ date +%s.%N
1627059870.945134901
This works with PostgreSQL 11:
# select to_timestamp (1627059870.945134901);
to_timestamp
-------------------------------
2021-07-23 19:04:30.945135+02
(1 row)
# select to_timestamp (1627059870.945134901)::date;
to_timestamp
--------------
2021-07-23
(1 row)
Related
I get a date format EPOCH in database table - "19072"
First I need to convert to time- 21/03/2022 and concatenate 23:59:59
date conversion reference - https://www.timeanddate.com/date/dateadded.html?d1=1&m1=1&y1=1970&type=add&ay=&am=&aw=&ad=19072&rec=
Now I need to convert "21/03/2022 23:59:59" to UTC +7:00(Jakarta, Indonesia)
Final expected output is - "22/03/2022 06:59:59"
You can add a number of days directly to a date:
select date '1970-01-01' + 19072 from dual;
21-MAR-22
or add an interval to a timestamp; which is probably more appropriate as you need to end up with a timestamp with time zone anyway, so this starts with a UTC value:
select timestamp '1970-01-01 00:00:00 UTC' + (19072 * interval '1' day) from dual;
21-MAR-22 00.00.00.000000000 PM UTC
Then you can add hours, minutes and seconds (or go ahead another day and subtract one second):
select
timestamp '1970-01-01 00:00:00 UTC'
+ (19072 * interval '1' day)
+ (23 * interval '1' hour)
+ (59 * interval '1' minute)
+ (59 * interval '1' second)
from dual;
21-MAR-22 11.59.59.000000000 PM UTC
and convert to your target time zone with at time zone:
select
(
timestamp '1970-01-01 00:00:00 UTC'
+ (19072 * interval '1' day)
+ (23 * interval '1' hour)
+ (59 * interval '1' minute)
+ (59 * interval '1' second)
)
at time zone 'Asia/Jakarta'
from dual;
22-MAR-22 06.59.59.000000000 AM ASIA/JAKARTA
and then for display purposes, convert to a string in the format you want:
select
to_char(
(
timestamp '1970-01-01 00:00:00 UTC'
+ (19072 * interval '1' day)
+ (23 * interval '1' hour)
+ (59 * interval '1' minute)
+ (59 * interval '1' second)
)
at time zone 'Asia/Jakarta',
'DD/MM/YYYY HH24:MI:SS'
) as result
from dual;
22/03/2022 06:59:59
You can simplify a bit by modifying your epoch, though it looks a bit odd:
select
to_char(
(
timestamp '1970-01-01 23:59:59 UTC'
+ (19072 * interval '1' day)
)
at time zone 'Asia/Jakarta',
'DD/MM/YYYY HH24:MI:SS'
) as result
from dual;
22/03/2022 06:59:59
(I'd probably prefer to keep the usual epoch and do the extra explicit interval additions...)
db<>fiddle
Only format as a string to display it. If you need to pass the value somewhere else then leave it as a timestamp with time zone, or if necessary cast that to a plain timestamp or even a date.
I have a data set with the following columns
time date
1310 2020-06-01
1425 2020-06-22
1640 2020-06-29
My desired final output is a column in datetime format that looks as such
datetime
2020-06-01 13:10:00.000
2020-06-22 14:25:00.000
2020-06-29 16:40:00.000
I have used the following command thus far to format the output the way I would like
CONCAT(date_string, ' ', substring(barstarttime, 1, 2), ':', substring(barstarttime, 3, 2), ':00.000'))
However, I have not had success in changing this to a datetime or timestamp.
Is there a function that can help me do so?
Thanks
Get the hours and minutes from the time string with SUBSTR. Then add the according intervals to the date.
I don't know whether Presto allows functions for the interval values. Please try:
select
date +
interval substr(time, 1, 2) hour +
interval substr(time, 3, 2) minute
from mytable;
If this doesn't work, try this instead:
select
date +
((interval '1' hour) * cast(substr(time, 1, 2) as integer)) +
((interval '1' minute) * cast(substr(time, 3, 2) as integer))
from mytable;
As mentioned, I don't know Presto. You may even have to cast the date to a timestamp first:
cast(date as timestamp) +
...
You can use date_parse function.
select date_parse(cast(date as varchar) || ' ' || time, '%Y-%m-%d %H%i') from
(values ('1300', date '2020-06-01')) as t(time, date)
You can use below in order to convert to timestamp
select *,
cast(date_col as timestamp) as ts
from T
Is there a way in Oralce PL/SQL to get the current timestamp as a NUMBER ?
Something like '1582185277302'
You can convert the current date/time to an epoch timestamp as follows:
(sysdate - date '1970-01-01') * 60 * 60 * 24
This gives you the number of seconds since January 1st, 1970.
If you want the results in milliseconds, then:
(cast(systimestamp as date) - date '1970-01-01') * 24 * 60 * 60 * 1000
+ mod( extract(second from systimestamp), 1) * 1000
Unix timestamps are in the UTC time zone. If your timestamp is in the UTC time zone then you can use:
( TRUNC( your_timestamp, 'MI' ) - DATE '1970-01-01' ) * 24 * 60 * 60 * 1000
+ EXTRACT( SECOND FROM your_timestamp ) * 1000
If your timestamps have a time zone then:
( TRUNC( your_timestamp AT TIME ZONE 'UTC', 'MI' ) - DATE '1970-01-01' ) * 24 * 60 * 60 * 1000
+ EXTRACT( SECOND FROM your_timestamp ) * 1000
If you need to handle leap seconds then you can use this answer.
If you subtract a fixed timestamp from systimestamp you get an interval:
select systimestamp - timestamp '1970-01-01 00:00:00 UTC' as diff
from dual;
DIFF
----------------------
+18312 10:05:29.674905
You can then extract and manipulate the elements of that to get the epoch time, using an inline view or CTE to avoid repeating the interval generation:
with t (diff) as (
select systimestamp - timestamp '1970-01-01 00:00:00 UTC'
from dual
)
select trunc(1000 * (
extract (day from diff) * 24 * 60 *60
+ extract (hour from diff) * 60 * 60
+ extract (minute from diff) * 60
+ extract (second from diff)
)) as epoch
from t;
EPOCH
-------------------
1582193129829
Adding all the extracts together gives you the total number of seconds, including fractions; multiplying by 1000 gives you milliseconds but will still have fractions (depending on the precision your platform supports); truncating that gives you just milliseconds.
This takes the time zone into account (epoch times are supposed to count from UTC); but doesn't allow for leap seconds.
As a further demo, using a fixed time in an arbitrary time zone to get the result in your question:
with t (diff) as (
select timestamp '2020-02-20 02:54:37.302789 America/New_York' - timestamp '1970-01-01 00:00:00 UTC'
from dual
)
select trunc(1000 * (
extract (day from diff) * 24 * 60 *60
+ extract (hour from diff) * 60 * 60
+ extract (minute from diff) * 60
+ extract (second from diff)
)) as epoch
from t;
EPOCH
-------------------
1582185277302
When subtracting timestamps the return value is an interval data-type. Is there an elegant way to convert this value into the total number of (milli/micro) seconds in the interval, i.e. an integer.
The following would work, but it's not very pretty:
select abs( extract( second from interval_difference )
+ extract( minute from interval_difference ) * 60
+ extract( hour from interval_difference ) * 60 * 60
+ extract( day from interval_difference ) * 60 * 60 * 24
)
from ( select systimestamp - (systimestamp - 1) as interval_difference
from dual )
Is there a more elegant method in SQL or PL/SQL?
An easy way:
select extract(day from (ts1-ts2)*86400) from dual;
The idea is to convert the interval value into days by times 86400 (= 24*60*60).
Then extract the 'day' value which is actually second value we wanted.
I hope this help:
zep#dev> select interval_difference
2 ,sysdate + (interval_difference * 86400) - sysdate as fract_sec_difference
3 from (select systimestamp - (systimestamp - 1) as interval_difference
4 from dual)
5 ;
INTERVAL_DIFFERENCE FRACT_SEC_DIFFERENCE
------------------------------------------------------------------------------- --------------------
+000000001 00:00:00.375000 86400,375
With your test:
zep#dev> select interval_difference
2 ,abs(extract(second from interval_difference) +
3 extract(minute from interval_difference) * 60 +
4 extract(hour from interval_difference) * 60 * 60 +
5 extract(day from interval_difference) * 60 * 60 * 24) as your_sec_difference
6 ,sysdate + (interval_difference * 86400) - sysdate as fract_sec_difference
7 ,round(sysdate + (interval_difference * 86400) - sysdate) as sec_difference
8 ,round((sysdate + (interval_difference * 86400) - sysdate) * 1000) as millisec_difference
9 from (select systimestamp - (systimestamp - 1) as interval_difference
10 from dual)
11 /
INTERVAL_DIFFERENCE YOUR_SEC_DIFFERENCE FRACT_SEC_DIFFERENCE SEC_DIFFERENCE MILLISEC_DIFFERENCE
------------------------------------------------------------------------------- ------------------- -------------------- -------------- -------------------
+000000001 00:00:00.515000 86400,515 86400,515 86401 86400515
zep#dev>
I've found this to work. Apparently, if you do arithmetics with timestamps they are converted to some internal datatype that, when substracted from each other, returns the interval as a number.
Easy? Yes. Elegant? No. Gets the work done? Oh yeah.
SELECT ( (A + 0) - (B + 0) ) * 24 * 60 * 60
FROM
(
SELECT SYSTIMESTAMP A,
SYSTIMESTAMP - INTERVAL '1' MINUTE B
FROM DUAL
);
Unfortunately, I don't think that there is an alternative (or more elegant) way of calculating total seconds from an interval type in pl/sql. As this article mentions:
... unlike .NET, Oracle provides no simple equivalent to TimeSpan.TotalSeconds.
therefore extracting day, hour etc from the interval and multiplying them with corresponding values seems like the only way.
Based on zep's answer, I wrapped things up into a function for your convenience:
CREATE OR REPLACE FUNCTION intervalToSeconds(
pMinuend TIMESTAMP , pSubtrahend TIMESTAMP ) RETURN NUMBER IS
vDifference INTERVAL DAY TO SECOND ;
vSeconds NUMBER ;
BEGIN
vDifference := pMinuend - pSubtrahend ;
SELECT EXTRACT( DAY FROM vDifference ) * 86400
+ EXTRACT( HOUR FROM vDifference ) * 3600
+ EXTRACT( MINUTE FROM vDifference ) * 60
+ EXTRACT( SECOND FROM vDifference )
INTO
vSeconds
FROM DUAL ;
RETURN vSeconds ;
END intervalToSeconds ;
Use following query:
select (cast(timestamp1 as date)-cast(timestamp2 as date))*24*60*60)
Similar to #Zhaoping Lu answer but directly extracting seconds instead of getting them from the number of days.
SELECT extract(second from (end_date - start_date)) as "Seconds number"
FROM my_table
(worked on PostgresSQL 9.6.1)
A shorter method to convert timestamp to nanoseconds.
SELECT (EXTRACT(DAY FROM (
SYSTIMESTAMP --Replace line with desired timestamp --Maximum value: TIMESTAMP '3871-04-29 10:39:59.999999999 UTC'
- TIMESTAMP '1970-01-01 00:00:00 UTC') * 24 * 60) * 60 + EXTRACT(SECOND FROM
SYSTIMESTAMP --Replace line with desired timestamp
)) * 1000000000 AS NANOS FROM DUAL;
NANOS
1598434427263027000
A method to convert nanoseconds to timestamp.
SELECT TIMESTAMP '1970-01-01 00:00:00 UTC' + numtodsinterval(
1598434427263027000 --Replace line with desired nanoseconds
/ 1000000000, 'SECOND') AS TIMESTAMP FROM dual;
TIMESTAMP
26/08/20 09:33:47,263027000 UTC
As expected, above methods' results are not affected by time zones.
A shorter method to convert interval to nanoseconds.
SELECT (EXTRACT(DAY FROM (
INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval --Maximum value: INTERVAL '+694444 10:39:59.999999999' DAY(6) TO SECOND(9) or up to 3871 year
) * 24 * 60) * 60 + EXTRACT(SECOND FROM (
INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval
))) * 1000000000 AS NANOS FROM DUAL;
NANOS
1598434427263027000
A method to convert nanoseconds to interval.
SELECT numtodsinterval(
1598434427263027000 --Replace line with desired nanoseconds
/ 1000000000, 'SECOND') AS INTERVAL FROM dual;
INTERVAL
+18500 09:33:47.263027
Replace 1000000000 by 1000, for example, if you'd like to work with milliseconds instead of nanoseconds.
I've tried some of posted methods, but a got the exception "ORA-01873: the leading precision of the interval is too smalll" when multiplying the interval by 86400, so I've decided do post the methods that works for me.
SELECT to_char(ENDTIME,'yyyymmddhh24missff')-to_char(STARTTIME,'yyyymmddhh24missff') AS DUR
FROM DUAL;
yyyymmddhh24miss- WILL GIVE DURATION IN SEC
yyyymmddhh24mi DURATION IN MIN
yyyymmddhh24 - DURATION - HOURS
yyyymmdd DURATION IN DAYS
i have 2 rows in a column, one feeding me the julian date (number of days since Jan 1, 1970, with that day being 1), and the second column is the number of minutes past midnight of the current day (why it was done this way, i have no idea).
i would like to get my sql query to create a timestamp out of these two columns.
if i had access to the data ahead of time, i could do something like SELECT timestamp '1970-01-01 00:00:00' + INTERVAL 'X DAYS' + INTERVAL 'Y MINUTES' AS my_time FROM mytable, but since X and Y are actual members of the table i'm querying, it's not that simple.
anyone have any suggestions?
essentially, i'm looking for the equivalent [legal] solution:
SELECT timestamp '1970-01-01 00:00:00' + INTERVAL 'my_col1 DAYS' + INTERVAL 'my_col2 MINUTES' AS my_time FROm mytable
i can get my server-side code to do it for me, but i would love it if i could build it into my query.
You can construct the interval strings and then cast them to the interval type:
SELECT
timestamp '1970-01-01 00:00:00' +
cast(my_col1 || ' DAYS' AS interval) +
cast(my_col2 || ' MINUTES' AS interval) my_time FROM mytable
Without resorting to string substitution or concatenation:
SELECT
timestamp '1970-01-01 00:00:00' +
my_col1 * interval '1 DAY' +
my_col2 * interval '1 MINUTE' FROM mytable