I got parameter
:dateFrom
which gonna be used as an argument in a function as a TIMESTAMP. I need to add to :dateFrom + 7 hours, how can I do that?
If your parameter is not already a timestamp, use to_timestamp or to_date to convert it:
to_timestamp(dateFrom,'mm/dd/yyyy hh24:mi:ss')
(substitute the appropriate mask based on the format of your input parameter)
Then just add 7/24.
to_timestamp(dateFrom,'mm/dd/yyyy hh24:mi:ss') + 7/24;
Adding 1 adds a full day, so adding 1/24 adds 1 hour.
This can also be done with the INTERVAL operator:
to_timestamp(dateFrom,'mm/dd/yyyy hh24:mi:ss') + INTERVAL '7' hour
Here is some PL/SQL that will:
DECLARE
dateFrom TIMESTAMP;
BEGIN
dateFrom := SYSTIMESTAMP;
DBMS_OUTPUT.PUT_LINE('BEFORE :: ' || dateFrom);
dateFrom := dateFrom + INTERVAL '2' HOUR;
DBMS_OUTPUT.PUT_LINE('AFTER :: ' || dateFrom);
END;
/
Look into the INTERVAL operator.
You can do like this,
select dateFrom + interval '7' hours from dual
In the arithmetic of the dates, in Oracle, when you add a number, it is intended as NUMBER OF DAYS.
7 hours are 7/24 days, so you have simply to add 7/24.
Related
Im trying to add hours to midnight of today eg: like 27 hours
I have tried various methods from the internet but am getting the trunc of the dated expected. eg 23-nov-2022 not 23-nov-2022 03:00. when i run it outside my pl/sql procedure/block i get the desired output
the select:
select to_char(to_date(sysdate,'DD-MON-RRRR HH:MI')+hours/24,'DD-MON-RRRR HH:MI') into v_from from dual;
I need some expert assistance
Add an INTERVAL DAY TO SECOND data type to SYSDATE TRUNCated back to midnight:
DECLARE
v_from DATE;
BEGIN
SELECT TRUNC(sysdate) + INTERVAL '27' HOUR
INTO v_from
FROM DUAL;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_from,'DD-MON-RRRR HH:MI'));
END;
/
or, more simply:
DECLARE
v_from DATE;
BEGIN
v_from := TRUNC(sysdate) + INTERVAL '27' HOUR;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_from,'DD-MON-RRRR HH:MI'));
END;
/
or, dynamically, with the NUMTODSINTERVAL function:
DECLARE
v_from DATE;
v_hours NUMBER(3,0) := 27;
BEGIN
v_from := TRUNC(sysdate) + NUMTODSINTERVAL(v_hours,'HOUR');
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_from,'DD-MON-RRRR HH:MI'));
END;
/
fiddle
Trunc SYSDATE to get midnight. Then add hours: 1 hour is 1/24 day so you'd add the number of hours divided by 24. Example.
koen>DECLARE
2 l_date DATE;
3 l_hours NUMBER := 27;
4 BEGIN
5 l_date := TRUNC(SYSDATE) + 27/24;
6 dbms_output.put_line('l_date is: '||TO_CHAR(l_date,'DD-MON-YYYY HH24:MI'));
7 END;
8* /
l_date is: 23-NOV-2022 03:00
PL/SQL procedure successfully completed.
koen>
The select from dual is not advised, you can just assign a variable in pl/sql using the assignment operator :=. The select from dual requires an additional context switch (invoke the sql engine from within pl/sql).
I have a table which contains DateTime in the following format
'MM/DD/YYYY HH:MI'
now I am trying to convert this time into Teradata Timestamp but getting an error.
What I have tried is:
select cast('4/13/2022 0:00' AS TIMESTAMP(0) Format 'mm/dd/yyyyBhh:mi')
but it return invalid timestamp error.
Any method for this?
Best regards.
You've got single digit month and hour values in there. I don't think there's any way to make Teradata play nice with those, other than adding the leading 0s.
I think this should work but you'll want to test it thoroughly.
select cast (regexp_replace('4/13/2022 0:00', '\b([0-9])\b', '0\1') AS TIMESTAMP(0) Format 'mm/dd/yyyyBhh:mi')
after different solutions, this worked.
CASE WHEN CHAR_LENGTH( STRTOK(ACT_TIME, '/', 1)) = 1 THEN TO_TIMESTAMP( '0' || ACT_TIME, 'MM/DD/YYYY HH24:MI') END ACT_TIME_TIMESTAMP
,CASE WHEN CHAR_LENGTH( STRTOK(ACT_TIME, '/', 1)) = 1 THEN CAST(TO_TIMESTAMP( '0' || ACT_TIME, 'MM/DD/YYYY HH24:MI') AS DATE) END ACT_TIME_DATE
,CASE WHEN CHAR_LENGTH( STRTOK(ACT_TIME, '/', 1)) = 1 THEN CAST(TO_TIMESTAMP( '0' || ACT_TIME, 'MM/DD/YYYY HH24:MI') AS TIME) END ACT_TIME_DATE
select TO_NUMBER (SUBSTR(10.31, INSTR (10.31, '.') + 1)) from dual
Above query returns 31 as the output. But below query returns 3 as the output.
select TO_NUMBER (SUBSTR(10.30, INSTR (10.30, '.') + 1)) from dual
How could I get the 30 as the output instead of the 3?
As it seems (from comments) that you are starting with a numeric value that you want to turn into words, you should begin by splitting it into dollars and cents.
If you really need to use substr etc, then you could start with a known format, such as to_char(amount,'fm9990.00'), so it will be a string with exactly two decimal places. However, if you have the numeric value it would be easier to convert it into the desired units using arithmetic functions. Whole dollars are trunc(amount) and cents are 100 * mod(amount,1).
Another issue is that the 'Jsp' date format approach can't handle zeroes. If you are using Oracle 12.2 or later there is a workaround using the default on conversion error clause:
create table demo
( amount number(6,2) );
insert into demo values (10.3);
insert into demo values (.25);
insert into demo values (25);
select amount
, nvl(to_char(to_date(trunc(amount) default null on conversion error,'J'),'Jsp'),'Zero') as dollars
, nvl(to_char(to_date(100 * mod(amount,1) default null on conversion error,'J'),'Jsp'),'Zero') as cents
from demo;
AMOUNT DOLLARS CENTS
-------- ------------ -------------
10.30 Ten Thirty
25.00 Twenty-Five Zero
0.25 Zero Twenty-Five
In 12.1 you could get around it using an inline function (maybe not a bad idea even in later versions, to simplify the rest of the query):
with
function to_words(num number) return varchar2 as
begin
return
case num
when 0 then 'Zero'
else to_char(to_date(num,'J'),'Jsp')
end;
end;
select amount
, to_words(trunc(amount)) as dollars
, to_words(100 * mod(amount,1)) as cents
from demo;
For values greater than 5373484 (the Julian representation of date '9999-12-31'), you can use this from Ask Tom: Spell the number (converted here to a WITH clause, but you can create it as a standalone function):
with function spell_number
( p_number in number )
return varchar2
as
-- Tom Kyte, 2001:
-- https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1407603857650
l_num varchar2(50) := trunc(p_number);
l_return varchar2(4000);
type myarray is table of varchar2(15);
l_str myarray :=
myarray
( ''
, ' thousand '
, ' million '
, ' billion '
, ' trillion '
, ' quadrillion '
, ' quintillion '
, ' sextillion '
, ' septillion '
, ' octillion '
, ' nonillion '
, ' decillion '
, ' undecillion '
, ' duodecillion ');
begin
for i in 1 .. l_str.count loop
exit when l_num is null;
if substr(l_num, length(l_num) -2, 3) <> 0 then
l_return := to_char(to_date(substr(l_num, length(l_num) - 2, 3), 'J'), 'Jsp') || l_str(i) || l_return;
end if;
l_num := substr(l_num, 1, length(l_num) - 3);
end loop;
return l_return;
end spell_number;
select amount
, spell_number(trunc(amount)) as dollars
, spell_number(100 * mod(amount,1)) as cents
from demo
/
I am actually surprised that your current query is even running without error, given that Oracle's SUBSTR function is supposed to operate on strings, not numbers. That being said, if you properly use your current query with strings, then it works:
SELECT TO_NUMBER(SUBSTR('10.30', INSTR ('10.30', '.') + 1)) FROM dual; -- returns 30
A more compact (though not necessarily more performant) way of doing this might be to use REGEXP_SUBSTR:
SELECT REGEXP_SUBSTR('10.30', '[0-9]+$') FROM dual;
This would retain only digits appearing after the decimal point, in the case that a decimal point be present. Otherwise, it would just return all numbers for inputs which have no decimal component.
I have this anonymous block:
DECLARE
V_DATA DATE;
BEGIN
V_DATA := '01-GEN-2000';
HR.STATISTICHE.RATINGOPERATORI (V_DATA);
COMMIT;
END;
but I would to generate the date in a random way. How can I do?
You can generate random dates between two dates ,as displayed in the query below .Random Dates are generated between 1-jan-2000 and 31-dec-9999
SELECT TO_DATE(
TRUNC(
DBMS_RANDOM.VALUE(TO_CHAR(DATE '2000-01-01','J')
,TO_CHAR(DATE '9999-12-31','J')
)
),'J'
) FROM DUAL;
OR you can use
SELECT TO_DATE (
TRUNC (
DBMS_RANDOM.VALUE (2451545, 5373484)
)
, 'J'
)
FROM DUAL
In the above example ,the first value is 01-Jan-2000 and the second value id 31-dec-9999
To generate random date you can use
select to_date('2010-01-01', 'yyyy-mm-dd')+trunc(dbms_random.value(1,1000)) from dual
or for random datetime
select to_date('2010-01-01', 'yyyy-mm-dd')+dbms_random.value(1,1000) from dual
If you want to see it's logic, you can also use this code.
create or replace procedure genDate(result out nvarchar2) IS
year number;
month number;
day number;
Begin
year:=FLOOR(DBMS_RANDOM.value(2000,2100));
month:=FLOOR(DBMS_RANDOM.value(1,12));
IF month=2 and (year/4)=0 and (year/100)!=0 then
day:=FLOOR(DBMS_RANDOM.value(1,29));
ELSIF month=2 or (year/100)=0 then
day:=FLOOR(DBMS_RANDOM.value(1,28));
ELSIF MOD(month,2)=1 then
day:=FLOOR(DBMS_RANDOM.value(1,31));
ELSIF MOD(month,2)=0 and month!=2 then
day:=FLOOR(DBMS_RANDOM.value(1,30));
END IF;
result:=month||'-'||day||'-'||year;
End;
here is one more option to generate date going back from now where 365 - days quanitity to move back from today, 'DD.MM.YYYY'- mask
to_char(sysdate-dbms_random.value()*365, 'DD.MM.YYYY')
I needed to generate employee data for testing. Each employee needed a date of birth that put them between 16 and 65 years of age, and a date of hire sometime between their 16th birthday and SYSDATE. Here's how...
FUNCTION randomDateInRange(alpha IN DATE, omega IN DATE) RETURN DATE IS
BEGIN
RETURN alpha + DBMS_RANDOM.VALUE(0, omega - alpha);
END;
...and then, to use this function...
-- an employee can be any age from 16 to 65 years of age
DoB := randomDateInRange(
SYSDATE - INTERVAL '65' YEAR,
SYSDATE - INTERVAL '16' YEAR
);
-- an employee could have been hired any date since their sixteenth birthday
DoH := randomDateInRange(
DoB + INTERVAL '16' YEAR,
SYSDATE
);
I store some time values in sqlite in %H:%M string format (for example "15:43"), but I would like to get them out formatted in 12 hour format with AM/PM indicators (for example "3:43 PM"). Is this possible with sqlite (and if so, how), or do I need to do this in my application code?
Unless you extend sqlite with your own custom function, you'll have to do this is code.
sqlite's strftime date formatting function only supports a small subset of its C counterpart, insufficient for your problem. sqlite also lacks a selection construct like IF or CASE, making simple if/else impossible.
Some pseudo code to help you on the way:
if (hourpart of time >= 12)
subtract 12 from hours
append string " pm"
else // hourpart < 12
append string " am"
end if
In SQL you can accomplish this using the CASE syntax.
After taking a closer look at the problem:
SELECT (CASE HOUR(myTimeColumn) >= 12 WHEN 1 THEN
((HOUR(myTimeColumn) - 12) + '-' + MINUTE(myTimeColumn) + ' pm')
ELSE
(HOUR(myTimeColumn) + '-' + MINUTE(myTimeColumn) + ' am')
AS AmPmTime,
someOtherColumn
FROM myTable
I'm not entirely sure that all of that is valid SQLite syntax, but you should be able to correct the bugs.
There are a few special situation that are covered here. I'm using 'now' as a source, but you can adjust it for your string:
select
CASE
--For 00:05, for example.
WHEN (strftime('%H', 'now', 'localtime') - 12) = -12
THEN '12:' || strftime('%M', 'now', 'localtime') ||' '|| 'AM'
--For 12:05, for example.
WHEN (strftime('%H', 'now', 'localtime') - 12) = 0
THEN '12:' || strftime('%M', 'now', 'localtime') ||' '|| 'PM'
--other am time
WHEN (strftime('%H', 'now', 'localtime') - 12) < 0
THEN strftime('%H', 'now', 'localtime') ||':'||
strftime('%M', 'now', 'localtime') ||' '|| 'AM'
ELSE
--other pm time
(cast(strftime('%H', 'now', 'localtime') as integer) - 12) ||':'||
strftime('%M', 'now', 'localtime') ||' '|| 'PM'
END here_you_go_usa;
Do it in your application. Store it in normal 24h format in the database. In the database it can be stored as a Date entry instead of a string (correct me if im wrong)
As PoweRoy recomended, this belongs in the application.
It is recommended that any kind of data stored of used in communication uses a standard, locale-insensitive format: http://www.mihai-nita.net/article.php?artID=20051025a
Here's a working one.. Thanks to Tomas
SELECT
PatientName,
CASE WHEN
StrFTime('%H', AppointmentTime) % 12 = 0 THEN 12
ELSE StrFTime('%H', AppointmentTime) % 12 END
|| ':' ||
StrFTime('%M', AppointmentTime)
|| ' ' ||
CASE WHEN
StrFTime('%H', AppointmentTime) > 12 THEN 'PM'
ELSE 'AM' END
`APP_TIME`
From Patients;
OUTPUT
Abdul Salim, 12:05 PM