[英]Oracle Regular Expression for Date
I have the following anonymous block.我有以下匿名块。 I've written a small regular expression to accept the date.
我写了一个小的正则表达式来接受日期。 It is able to validate the day, month, and year.
它能够验证日、月和年。 Now I want to consider the only century year, and regexp should also allow year in RR format (Century year).
现在我想考虑唯一的世纪年,正则表达式也应该允许 RR 格式的年(世纪年)。 Also, I want to accept a day without a zero in the prefix;
另外,我想接受前缀中没有零的一天; currently, it is accepting this for the month only.
目前,它仅在当月接受这个。 Please see the scenarios below:
请看以下场景:
> 01/12/2154 (Do not accept, It's not a century year)
> 11/12/1996 (Do not accept, It's not a century year)
> 11/2/24 (Accept, and a plsql logic in IF condition could change it to 2024; Add 20 to it)
> 1/9/2020 (Accept)
> 01/02/2020 (Accept)
> 1/29/20 (Accept)
> 01/11/25 (Accept)
> 1/09/2021 (Accept)
** **
declare
date_v varchar2(40):= '01/01/2025';
date_n date;
begin
if regexp_like (date_v, '([0-9]|1[0-2])/([0-2][0-9]|3[0-1])/[0-9]{4}') then
-- logic
date_n:= TO_DATE(date_v,'MM/DD/YYYY');
dbms_output.put_line(date_n);
end if;
end;
You can do a regular expression on a date, but that is not a good way to check if a date is valid, it just checks if the format is ok.您可以对日期执行正则表达式,但这不是检查日期是否有效的好方法,它只是检查格式是否正确。 For example 30-FEB-2020 will pass your regex but that is not a valid date.
例如 30-FEB-2020 将通过您的正则表达式,但这不是有效日期。 The database can do the job for you instead.
数据库可以代替您完成这项工作。 I usually use something like this:
我通常使用这样的东西:
FUNCTION is_valid_date (date_str_i VARCHAR2, format_i VARCHAR2) RETURN VARCHAR2
/* check if date is valid */
AS
l_dummy_dt DATE;
date_not_valid_for_m EXCEPTION;
PRAGMA EXCEPTION_INIT(date_not_valid_for_m, -01839);
BEGIN
l_dummy_dt := TO_DATE(date_str_i,format_i);
RETURN 'Y';
EXCEPTION WHEN date_not_valid_for_m THEN
RETURN 'N';
END;
Note that it only fails if the TO_DATE returns ora-01839: date not valid for month specified, you can easily add the other possible errors or just use a WHEN OTHERS THEN RETURN 'N';请注意,仅当 TO_DATE 返回 ora-01839: date not valid for month specified 时才会失败,您可以轻松添加其他可能的错误,或者只使用 WHEN OTHERS THEN RETURN 'N';
Oracle is smart enough to recognize the string with or without 0 in date format. Oracle 足够聪明,可以识别日期格式中带或不带 0 的字符串。
So you can directly convert this string to TO_DATE('11/2/24', 'mm/dd/rrrr')
and for recognizing the current century, You can use the TRUNC
to century using the 'CC'
as follows:因此,您可以直接将此字符串转换为
TO_DATE('11/2/24', 'mm/dd/rrrr')
并识别当前世纪,您可以使用TRUNC
到使用'CC'
世纪,如下所示:
SQL> SELECT
2 TO_DATE('11/2/24', 'mm/dd/rrrr') YOUR_DATE,
3 CASE
4 WHEN TRUNC(TO_DATE('11/2/24', 'mm/dd/rrrr'), 'CC') = TRUNC(SYSDATE, 'CC') THEN
5 'ACCEPT'
6 ELSE
7 'REJECT'
8 END RESULT
9 FROM
10 DUAL;
YOUR_DATE RESULT
----------- ------
02-NOV-2024 ACCEPT
SQL>
Result of the query with another date from the past century:上个世纪的另一个日期的查询结果:
SQL> SELECT
2 TO_DATE('11/12/1996', 'mm/dd/rrrr') YOUR_DATE,
3 CASE
4 WHEN TRUNC(TO_DATE('11/12/1996', 'mm/dd/rrrr'), 'CC') = TRUNC(SYSDATE, 'CC') THEN
5 'ACCEPT'
6 ELSE
7 'REJECT'
8 END RESULT
9 FROM
10 DUAL;
YOUR_DATE RESULT
----------- ------
12-NOV-1996 REJECT
SQL>
Note : I have used 'rrrr'
for a year as it will convert any two-digit years to the year falling in 1950-2049.注意:我已经使用了
'rrrr'
一年,因为它将任何两位数的年份转换为 1950-2049 年的年份。
Try this one:试试这个:
with t(date_col) as (
select '01/01/2014' from dual
union all
select '1/2/2014' from dual
union all
select '01/3/2014' from dual
union all
select '1/04/2014' from dual
union all
select '11/1/14' from dual)
select date_col,
case
when regexp_instr(date_col, '^\d/\d/\d{4}$') = 1 then
'd/m/yyyy'
when regexp_instr(date_col, '^\d{2}/\d/\d{4}$') = 1 then
'dd/m/yyyy'
when regexp_instr(date_col, '^\d/\d{2}/\d{4}$') = 1 then
'd/mm/yyyy'
when regexp_instr(date_col, '^\d{2}/\d{2}/\d{4}$') = 1 then
'dd/mm/yyyy'
else
'Unknown format'
end date_format
from t;
DATE_COL DATE_FORMAT
---------- --------------
01/01/2014 dd/mm/yyyy
1/2/2014 d/m/yyyy
01/3/2014 dd/m/yyyy
1/04/2014 d/mm/yyyy
11/1/14 Unknown format
Refer to this link:参考这个链接:
Date validation with regular expression is difficult, very difficult.使用正则表达式进行日期验证很困难,非常困难。 THr problem being that months have differing number of days, and 29-Feb is valid only in certain years.
问题是月份的天数不同,而 2 月 29 日仅在某些年份有效。 Your request is to have multiple valid formats greatly compounding.
您的要求是使多种有效格式大大复合。
The following function validates dates in the ISO-8601 format (YYYY-MM-DD), and only that format, but it does validate the correct number of days in each month for the dates 0001-01-01 through 9999-12-31, including leap days (29-Feb) when valid.以下 function 验证 ISO-8601 格式 (YYYY-MM-DD) 的日期,并且仅验证该格式,但它确实验证日期 0001-01-01 到 9999-12-31 的每个月的正确天数,包括有效的闰日(2 月 29 日)。 but again just 1 format.
但又只是一种格式。 Recommendation do not try validating dates with regular expression, esp multiple formats.
建议不要尝试使用正则表达式验证日期,尤其是多种格式。
create or replace function valid_iso_date (iso_date_string varchar2)
return date
is
iso_date_pattern constant varchar2(256) :=
'^((0[0-9]{2}[1-9]|[1-9][0-9]{3})-((0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01])|02-(0[1-9]|1[0-9]|2[0-8])|(0[469]|11)-(0[1-9]|[12][0-9]|30))$)|^(\d\d(0[48]|[2468][048]|[13579][26])-02-29$)';
result_date date := null;
begin
if regexp_like(iso_date_string, iso_data_pattern)
then
result_date := to_date(iso_date_string,'yyyy-mm-dd');
end if;
return result_date;
end valid_iso_date;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.