How to convert YY to YYYY ORACLE - oracle

How to convert YY to YYYY, example below, if I run example below I will receive for year '0007':
DECLARE
lv_promcode_txt VARCHAR(6) := 'A0807X';
lv_prommth_txt VARCHAR2(7);
lv_promyear_txt VARCHAR2(7);
BEGIN
lv_prommth_txt := SUBSTR(lv_promcode_txt, 2,2);
DBMS_OUTPUT.PUT_LINE('Month of promo code is: '||
TO_(TO_DATE(lv_prommth_TXT,'MM'), 'MONTH'));
lv_promyear_txt := SUBSTR(lv_promcode_txt, 4,2);
DBMS_OUTPUT.PUT_LINE('Year of promo code is: '||TO_CHAR(TO_DATE
(lv_promyear_txt, 'YYYY'),'YYYY'));
END;

Your format mask is wrong. Example:
select TO_CHAR(TO_DATE (SUBSTR('A0807X', 4,2), 'YY'),'YYYY') from dual
returns 2007

Replace your last DBMS_OUTPUT.PUT_LINE part of the code with
DBMS_OUTPUT.PUT_LINE('Year of promo code is ( Style 1 ) : '||TO_CHAR(TO_DATE(lv_promyear_txt, 'YYYY'),'YYYY'));
DBMS_OUTPUT.PUT_LINE('Year of promo code is ( Style 2 ) : '||TO_CHAR(TO_DATE(lv_promyear_txt, 'RRRR'),'YYYY'));
Just changing YYYY literal RRRR is enough in TO_DATE function.
This concept is related to year 2k problem.
For a date TO_DATE('18', 'RRRR') gives the result 2018 as year ( for
the current century, and the last two digits of years are between 00-49 ),
while
For a date TO_DATE('74', 'RRRR') gives the result 1974 as year ( for
the previous century, and the last two digits of years are between 50-99 )

Related

Convert Mon yyyy to yyyy-mm-dd format in oracle

I am sending date (August 2022) from java as a string to oracle plsql and i want to change the format from August 2022 to 01-08-22 in plsql. how can i do it ?
below is a part of code:
PROCEDURE CHECK_DUMMY
(
IN_SL_NO IN SIGN.SL_NO%TYPE,
IN_MONTH IN SIGN.MONTH%TYPE
)
AS
V_MON DATE := TO_DATE(IN_MONTH , 'DD-MM-YYYY');
You want to use the format model Month YYYY and specify the language you are using:
CREATE PROCEDURE CHECK_DUMMY
(
IN_SL_NO IN SIGN.SL_NO%TYPE,
IN_MONTH IN SIGN.MONTH%TYPE
)
AS
V_MON DATE := TO_DATE(IN_MONTH , 'Month YYYY', 'NLS_DATE_LANGUAGE=English');
BEGIN
-- Do Something
DBMS_OUTPUT.PUT_LINE( v_mon );
END;
/
Then:
BEGIN
CHECK_DUMMY(1, 'August 2022');
END;
/
Outputs:
2022-08-01 00:00:00
Note: In Oracle, a DATE is a binary data type comprising of 7 bytes that represent century, year-of-century, month, day, hours, minutes and seconds and always has those 7 components and is never stored with any particular format. If you want to output 01-08-22 for display purposes then use TO_CHAR(v_mon, 'DD-MM-YY') to convert the date to a formatted string.
fiddle

Oracle PLSQL get difference between 2 datetime fields ignoring days

I would like to find the simplest way of calculating the difference in hours between 2 dates from Oracle datetime fields whilst ignoring the days, months & years portion. For example:
Datetime 1 (DATE variable) = 10/05/2017 16:00:00
Datetime 2 (DATE variable) = 15/05/2017 19:34:23
Required result (NUMBER output) = 3.576 hours
This is formula will be used in a PLSQL procedure, the output needs to be a number as above. I would imagine some combination of TO_DATE & TRUNC might work. Any help would be most appriciated and apologies if this is a duplicate question.
Use the sssss date mask to get just the time element as the number of seconds since midnight. Then it's just a matter of simple arithmentic:
select (to_number(to_char(datetime2, 'sssss'))
- to_number(to_char(datetime1, 'sssss')) / 3600 as diff_hours
from dual;
PL/SQL version is the same....
declare
Datetime1 DATE := to_date('10/05/2017 16:00:00', 'dd/mm/yyyy hh24:mi:ss');
Datetime2 DATE := to_date('15/05/2017 19:34:23', 'dd/mm/yyyy hh24:mi:ss');
hours_diff number;
begin
hours_diff := (to_number(to_char(datetime2, 'sssss'))
- to_number(to_char(datetime1, 'sssss'))) / 3600 ;
dbms_output.put_line(hours_diff);
end;

How to get year with fractional part from date in Oracle?

I need a PL/SQL function that takes a date and returns the year as a number, including a fractional part from the days. For example, 1995-01-01 would be 1995.000 and 2015-11-24 would be 2015.897. This is what I managed to produce:
CREATE OR REPLACE FUNCTION year_fraction (in_date DATE)
RETURN NUMBER
IS
year NUMBER;
days NUMBER;
total_days NUMBER;
BEGIN
year := EXTRACT(YEAR FROM in_date);
days := in_date - TRUNC(in_date, 'YEAR');
total_days := ADD_MONTHS(TRUNC(in_date, 'YEAR'), 12) - TRUNC(in_date, 'YEAR');
RETURN year + days / total_days;
END year_fraction;
It works, but it feels like to much work to solve quite a simple problem. Can this be done in a neater way?
So you want the decimal part as percentage of days passed in current year. It would be a simple date arithmetic to divide the day of the year with total days in that year.
SQL> SELECT EXTRACT(YEAR FROM SYSDATE)
2 ||'.'
3 ||TRUNC(TO_NUMBER(TO_CHAR(SYSDATE, 'DDD'))/
4 (add_months(TRUNC(SYSDATE,'year'), 12) - TRUNC(SYSDATE,'year'))*1000) my_format
5 FROM DUAL;
MY_FORMAT
--------------------------------------------------------------------------------
2015.898
Eventually I ended up using this solution. It is quite similar to what I started out with in the question, but involves fewer function calls and is a bit more condensed.
CREATE OR REPLACE FUNCTION fractional_year (in_date DATE)
RETURN NUMBER
IS
year DATE;
BEGIN
year := TRUNC(in_date, 'YEAR');
-- Year + Days passed so far / Total number of days in year
RETURN EXTRACT(YEAR FROM year) + (in_date - year) / (ADD_MONTHS(year, 12) - year);
END fractional_year;

date difference between two date datetype variable in HH:MM:SI in Oracle [duplicate]

This question already has answers here:
In Oracle, is there a function that calculates the difference between two Dates?
(5 answers)
Closed 8 years ago.
I am facing an issue where I have to take the difference between two date datetype variables in HH:MM:SS AM. For example if date1 stores 23-DEC-2014 02:00:00 PM and date2 stores 24-DEC-2014 02:00:00 PM then date2 - date1 should return 24:00:00.
I tried different to_char and likewise methods.
Can you please suggest what I should do to resolve this issue.
As you have plain DATE, the difference between two dates is expressed in fractional days. Some little arythmetics as explained in the related questions might help.
One other approach would be to cast the difference to an INTERVAL using NUMTODSINTERVAL. However, this does not work out-of-the-box, as (of 11g at least), the TO_CHAR function does not supports correctly INTERVAL.
However, as a workaround that is not provided in the related answers (or do I missed it?), you can cast to INTERVAL DAY TO SECOND using the right precision to achieve (more or less) what you are looking for:
Here is an example
with testdata as (select to_date('12/12/2014 09:00:00','DD/MM/YYYY HH:MI:SS') a,
to_date('10/11/2014 11:30:14','DD/MM/YYYY HH:MI:SS') b from dual)
select a-b "days",
numtodsinterval(a-b, 'DAY') "ds interval",
CAST(numtodsinterval(a-b, 'DAY') AS INTERVAL DAY(3) TO SECOND(0))
-- ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- cast to 3 digit days interval -- no fractional seconds
from testdata
Producing (formatted as rows for display purpose):
days
31.8956712962962962962962962962962962963
ds interval
+000000031 21:29:46.000000000
CAST(NUMTODSINTERVAL(A-B,'DAY') AS INTERVAL DAY(3) TO SECOND(0))
+031 21:29:46
I don't know if/how you can get rid of the leading sign though
Maybe this helps:
CREATE OR REPLACE FUNCTION get_date_diff(p_date1 IN DATE,
p_date2 IN DATE) RETURN VARCHAR2
IS
v_seconds NUMBER;
v_minutes NUMBER;
v_hours NUMBER;
v_time VARCHAR2(20);
BEGIN
v_seconds := (p_date2 - p_date1) * 24 * 60 * 60;
v_hours := FLOOR(v_seconds / 3600);
v_minutes := FLOOR((v_seconds - (v_hours * 3600)) / 60);
v_seconds := FLOOR(v_seconds - (v_hours * 3600) - (v_minutes * 60));
v_time := CASE WHEN v_hours < 100
THEN LPAD(TO_CHAR(v_hours), 2, '0')
ELSE TO_CHAR(v_hours)
END || ':' ||
LPAD(TO_CHAR(v_minutes), 2, '0') || ':' ||
LPAD(TO_CHAR(v_seconds), 2, '0');
RETURN v_time;
END;
/
SAMPLE INPUT
p_date1:=to_date('20/11/2014 11:30:45','DD/MM/YYYY HH:MI:SS')
p_date2 :=to_date('15/12/2014 09:00:00','DD/MM/YYYY HH:MI:SS')
SAMPLE OUTPUT
597:29:15

Change Excel date number to Oracle date

I'm having date as 41293 in oracle, how can i show it in DD/MON/YYYY format?
If i copy pasted it in Excel and change it to date format, it shows 01/19/13
Please help me.
The value you have is the number of days since the 30th of December 1899. Try:
select to_char(
to_date('1899-12-30', 'YYYY-MM-DD') + 41293,
'DD/MON/YYYY') from dual
Quoting from Oracle forum:
You need a tool to do that, since format is to tell oracle what type of format you have on your date type in the spreadsheet. While you may not have opted to format the date in Excel, it will appear as a date in the previewer. Use the format from this as a guide to enter into the datatype panel.
so, if you have a date that looks like this in the previewer, 19-jan-2006, then your format for the data type panel if you choose to insert that column is going to be DD-MON-YYYY,
Option 1:
Try using the below functions
FUNCTION FROMEXCELDATETIME ( ACELLVALUE IN VARCHAR2 )
RETURN TIMESTAMP
IS
EXCEL_BASE_DATE_TIME CONSTANT TIMESTAMP
:= TO_TIMESTAMP ( '12/31/1899',
'mm/dd/yyyy' ) ;
VAL CONSTANT NUMBER
:= TO_NUMBER ( NULLIF ( TRIM ( ACELLVALUE ),
'0' ) ) ;
BEGIN
RETURN EXCEL_BASE_DATE_TIME
+ NUMTODSINTERVAL ( VAL
- CASE
WHEN VAL >= 60
THEN
1
ELSE
0
END,
'DAY' );
END;
FUNCTION TOEXCELDATETIME ( ATIMESTAMP IN TIMESTAMP )
RETURN VARCHAR2
IS
EXCEL_BASE_DATE_TIME CONSTANT TIMESTAMP
:= TO_TIMESTAMP ( '12/31/1899',
'mm/dd/yyyy' ) ;
DIF CONSTANT INTERVAL DAY ( 9 ) TO SECOND ( 9 )
:= ATIMESTAMP
- EXCEL_BASE_DATE_TIME ;
DAYS CONSTANT INTEGER := EXTRACT ( DAY FROM DIF );
BEGIN
RETURN CASE
WHEN DIF IS NULL
THEN
''
ELSE
TO_CHAR ( DAYS
+ CASE
WHEN DAYS >= 60
THEN
1
ELSE
0
END
+ ROUND ( ( EXTRACT ( HOUR FROM DIF )
+ ( EXTRACT ( MINUTE FROM DIF )
+ EXTRACT ( SECOND FROM DIF )
/ 60 )
/ 60 )
/ 24,
4 ) )
END;
END;
Option 2:
The excel function would be =TEXT(B2,"MM/DD/YY"), to convert an Excel date value stored in B2. Then try using the test character in Oracle
If considering 1900 Jan 1st as start date,
SELECT
TO_CHAR ( TO_DATE ( '1900-01-01',
'YYYY-MM-DD' )
+ 41293,
'DD/MON/YYYY' )
FROM
DUAL
Microsoft's Documentation
Excel stores dates as sequential serial numbers so that they can be used in calculations. January 1, 1900 is serial number 1, and January 1, 2008 is serial number 39448 because it is 39,447 days after January 1, 1900.
Excel has a bug feature where it considers 1900 to be a leap year and day 60 is 1900-02-29 but that day never existed and a correction needs to be applied for this erroneous day.
It does also state that:
Microsoft Excel correctly handles all other leap years, including century years that are not leap years (for example, 2100). Only the year 1900 is incorrectly handled.
Therefore only a single correction is required.
So:
Before 1900-03-01 you can use DATE '1899-12-31' + value.
On or after 1900-03-01 you can use DATE '1899-12-30' + value.
Which can be put into a CASE statement:
SELECT CASE
WHEN value >= 1 AND value < 60
THEN DATE '1899-12-31' + value
WHEN value >= 60 AND value < 61
THEN NULL
WHEN value >= 61
THEN DATE '1899-12-30' + value
END AS converted_date
FROM your_table

Resources