I need to substract 30 days from a date in this format yyyyMMdd and convert it back to the same format. I do it this way.
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(
DATE_ADD(
FROM_UNIXTIME(UNIX_TIMESTAMP('20170720', 'yyyyMMdd')), -30
), 'yyyy-MM-dd'
), 'yyyyMMdd');
I don't like that I keep converting to and from time stamp. Can I make it shorter somehow?
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP('20170720', 'yyyyMMdd') - 30 * 86400, 'yyyyMMdd');
Related
I have these varchar : 20211026231735.
So I would like a query to substract actual sysdate to that date and convert the substraction to DAY HOURS AND SECONDS.
select TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS') - start_time from TABLEA where job_name='jOB_AA_BB';
I get 4220.
Any help please? Thanks
When you do datetime arithmetic with the DATE datatype, you get back a NUMBER of days. To get an INTERVAL you can subtract two TIMESTAMPs. You don't say what the data type is for start_time, but you might get away with this:
select localtimestamp - start_time
from tablea where job_name='jOB_AA_BB';
LOCALTIMESTAMP gives you a TIMESTAMP value in the current session time zone. There's also CURRENT_TIMESTAMP, which give you the same thing in a TIMESTAMP WITH TIME ZONE and SYSTIMESTAMP that gives you the database time in TIMESTAMP WITH TIME ZONE. You may need to convert your start_time to avoid time zone differences, if any.
You can us the function numtodsinterval to convert the results of date arithmetic to an interval. If necessary then use extract to pull out the needed components.
with tablea(job_name, start_time) as
(select 'jOB_AA_BB','20211026231735' from dual)
select numtodsinterval((SYSDATE - to_date( start_time,'yyyymmddhh24miss')),'hour') date_diff
from tablea where job_name='jOB_AA_BB' ;
with tablea(job_name, start_time) as
(select 'jOB_AA_BB','20211026231735' from dual)
select extract (hour from date_diff) || ':' || extract (minute from date_diff)
from (
select numtodsinterval((sysdate - to_date( start_time,'yyyymmddhh24miss')),'day') date_diff
from tablea where job_name='jOB_AA_BB'
);
NOTE: I am not sure how you got any result, other than an error, as your query winds up as a string - a string. You should not convert sysdate to a string but your string to a date (better yet store it as the proper data type - date).
You can convert the value to a date (rather than converting SYSDATE to a string) and then subtract and explicitly return the value as an INTERVAL DAY TO SECOND type:
SELECT (SYSDATE - TO_DATE('20211026231735', 'YYYYMMDDHH24MISS')) DAY TO SECOND
FROM DUAL;
Or, for your table:
SELECT (SYSDATE - TO_DATE(start_time,'YYYYMMDDHH24MISS')) DAY(5) TO SECOND
FROM TABLEA
WHERE job_name='jOB_AA_BB';
db<>fiddle here
I am working out of Oracle SQL. I have some dates that may have been poorly formatted when loading.
I'm doing a basic Max(date)-Min(Date) to get the difference in days. My results are:
+000000156 00:00:00.000000
+000000149 00:00:00.000000
+00 00:00:00.000000
I want to do some basic math with these date differences (average, etc) but I get an error message.
How do I convert these strings into numbers?
My guess is that the columns are timestamps, not dates, as the results are intervals not numbers. As you've found, Oracle have not got around to overloading the standard aggregate functions for intervals (vote for this feature on the Oracle Database Ideas forum) and currently you still have to either write your own or cast the timestamps to dates.
with demo (start_date, end_date) as
( select timestamp '2019-12-31 00:00:00', timestamp '2020-06-04 00:00:00' from dual union all
select timestamp '2020-01-31 00:00:00', timestamp '2020-06-28 00:00:00' from dual
)
select end_date - start_date as elapsed_interval
, cast(end_date as date) - cast(start_date as date) as elapsed_days
from demo;
ELAPSED_INTERVAL ELAPSED_DAYS
----------------------------- ------------
+000000156 00:00:00.000000000 156
+000000149 00:00:00.000000000 149
Basic math with dates:
date + number = date + number of days (also fractions)
SELECT SYSDATE + 1 FROM DUAL; -- tomorrow
date - number = date - number of days
SELECT SYSDATE - 1/24 FROM DUAL; -- one hour ago
date - date = numbers of days between dates (also fraction of days)
date + date = impossible
months_between(date1, date2) = returns months between two dates
add_months(date, number) = adds number (months) to date
if you have a string or number and it can be the n-th day of the year (for instance 156),
you can transform in date with TO_DATE('156', 'DDD')
if you have a string with a particular format, you can transform it in date with
TO_DATE(string, format of the date you imagine)
https://www.techonthenet.com/oracle/functions/to_date.php
if you need the opposite transform, that is transforming date to char (or number), use TO_CHAR(date, format of the date)
I have a unix timstamp with millsecond precision like below:
1523572200000
I need to convert it to timestamp(6). This is the format I need:
05-NOV-14 09.45.00.000000000 AM
(Fyi examples above are not matching dates, just using as example.)
What's the best way to go about this?
Thanks!
The following might work for you (where myunixtimestamp is the name of the column in which your Unix timestamps are stored):
SELECT TIMESTAMP'1970-01-01 00:00:00.000' + NUMTODSINTERVAL(myunixtimestamp/1000, 'SECOND')
FROM mytable;
For example,
SELECT TIMESTAMP'1970-01-01 00:00:00.000' + NUMTODSINTERVAL(1523572200000/1000, 'SECOND')
FROM dual;
gives a result of 2018-04-12 10:30:00.000000000 PM.
Hope this helps.
Assuming that current timestamp is: 1523572200000, try following:
select cast (to_date('1970-01-01', 'YYYY-MM-DD') + 1523572200000/1000/60/60/24 as timestamp) from dual;
where:
to_date('1970-01-01', 'YYYY-MM-DD') is epoch time
<unix_timestamp>/60/60/24 was divided by 1000 miliseconds 60 second and 60 minutes and 24 hours because in oracle we are adding days
I need to convert a date from a TextBox from date to epoch time so that I can insert it into Oracle DB.
I managed to convert from epoch to date as below, but couldn't find a way to convert it the other way.
SelectCommand="SELECT ID,
COMPANY,
FIRST_NAME,
LAST_NAME,
ID_NUMBER,
(SELECT TO_CHAR(TO_DATE('01-JAN-1970','DD/MM/YYYY')
+(TRAINING_DATE/60/60/24), 'MM/DD/YYYY') FROM dual) AS TRAINING_DATE,
(SELECT TO_CHAR(TO_DATE('01-JAN-1970','DD/MM/YYYY')
+(TRAINING_VALABILITY/60/60/24),'MM/DD/YYYY') FROM dual) AS TRAINING_VALABILITY
FROM CONTRACTORS
ORDER BY COMPANY"
Subtracting DATE '1970-01-01' from the value will give the number of days (and fractional hours/minutes/seconds) difference and then you can multiply by 24*60*60:
(date_value - DATE '1970-01-01')*24*60*60
Update:
Typically, epoch time is measured from 1970-01-01T00:00:00 UTC. If your date is not in UTC then you will need to convert time zones.
For example, if your date has the time zone Europe/Berlin:
( CAST(
FROM_TZ(
CAST( date_value AS TIMESTAMP ), -- Cast to timestamp
'Europe/Berlin' -- Convert to expected Time Zone
)
AT TIME ZONE 'UTC' -- Convert Time Zone to UTC
AS DATE -- Cast back to DATE data type
)
- DATE '1970-01-01'
)*24*60*60
db<>fiddle
UpdateCommand="UPDATE CONTRACTORS
SET COMPANY=:COMPANY,
FIRST_NAME=:FIRST_NAME,
LAST_NAME=:LAST_NAME,
ID_NUMBER=:ID_NUMBER,
TRAINING_DATE=(TO_DATE(:TRAINING_DATE, 'MM-DD-YYYY HH24:MI:SS') - TO_DATE('01-JAN-1970','DD/MM/YYYY'))*24*60*60,
TRAINING_VALABILITY=(TO_DATE(:TRAINING_VALABILITY, 'MM-DD-YY`enter code here`YY HH24:MI:SS') - TO_DATE('01-JAN-1970','DD/MM/YYYY'))*24*60*60
WHERE (ID=:ID)"
I use this solution which works correctly whether the input date, in local time, is during Daylight Saving Time (DST) or not.
SELECT Round((Cast(Sys_extract_utc( Cast( your_date_field AS TIMESTAMP )) AS DATE) - To_date('1970-01-01','YYYY-MM-DD HH24MISS')) *24*60*60) AS epoch FROM dual;
-- 'your_date_field'
-- '20210112' -> 1610427600 (no DST)
-- '20210512' -> 1620792000 (DST)
Need your help to conclude the query to fetch last date time of the sysdate month.
select to_char(last_day(sysdate),'DD-Mon-YYYY HH24:MI:SS') from dual
it gives last date as expected, but I need time as 23:59:00 which is not possible thru above query.
You could use TRUNC on next day i.e. SYSDATE + 1, and then subtract 60 seconds i.e. 60/86400 to get the desired output.
SQL> SELECT to_char((trunc(last_day(sysdate)) +1) - 60/86400,'DD-Mon-YYYY HH24:MI:SS') dt
2 FROM dual;
DT
--------------------
29-Feb-2016 23:59:00
SQL>
You could also use interval '1' minute or interval '60' second instead of 60/86400.
If you just want it for display for some reason you can hard-code the time into the format mask:
select to_char(last_day(sysdate), 'DD-Mon-YYYY "23:59:00"') from dual;
But you probably really want it as a date object, in which case you can add 23 hours and 59 minutes to the truncated (midnight) date, wchi is 1439 of the 1440 minutes in a day:
select to_char(trunc(last_day(sysdate)) + 1439/1440, 'DD-Mon-YYYY HH24:MI:SS')
from dual;
Or you can go to the next day and remove a minute, either with fractional days or with intervals:
select to_char(trunc(last_day(sysdate)) + interval '1' day - interval '1' minute,
'DD-Mon-YYYY HH24:MI:SS') from dual;
Generally if you're working with time periods you want to include up to 23:59:59, which you can also do with any of those methods, but as Damien_The_Unbeliever said in a comment, it's easier to compare against the start of the next period (e.g. < add_months(trunc(sysdate, 'MM'), 1). It's easy to accidentally miss part of a day by not taking the time into account properly, particularly if you actually have a timestamp rather than a date.