2011-11-05 59 views
2

有一些功能,可以验证格式AAAA/MM/GG(CCYY/MM/DD)返回True它是否有效或False否则日期?我的意思是关于真正有效的日期,不仅仅是语法。验证真正的约会

回答

3

这是非常快的,因为最简单的错误首先被捕获。

function IsValidDate(const S: string): boolean; 
var 
    y, m, d: Integer; 
const 
    DAYS_OF_MONTH: array[1..12] of integer = (31, 29, 31, 30, 31, 30, 31, 31, 30, 
    31, 30, 31); 
begin 
    result := false; 
    if length(S) <> 10 then Exit; 
    if (S[5] <> '/') or (S[8] <> '/') then Exit; 
    if not TryStrToInt(Copy(S, 1, 4), y) then Exit; 
    if not TryStrToInt(Copy(S, 6, 2), m) then Exit; 
    if not InRange(m, 1, 12) then Exit; 
    if not TryStrToInt(Copy(S, 9, 2), d) then Exit; 
    if not InRange(d, 1, DAYS_OF_MONTH[m]) then Exit; 
    if (not IsLeapYear(y)) and (m = 2) and (d = 29) then Exit; 
    result := true; 
end; 
+0

对不起,Andreas。 :)这工作(所以没有downvote),但提问者使用XE2。更好的答案是使用'TFormatSettings'的@Arjen。不过,我会允许这个异常,而不是像Arjen那样使用'TryStrToDate'。 –

+0

@Ken,谢谢。关于例外:取决于具体情况。 安德烈亚斯,并没有downvote从我。 –

+0

'StrToDate(S,Format)'方式不是XE2特有的,但不够严格。正。而且我认为真正的downvoter试图架设某人。 –

7

是 'AAAA' 一年 'GG' 天?

var 
    MyString: string; 
    MyDate: TDateTime; 
    settings: TFormatSettings; 
begin 
    settings.ShortDateFormat := 'yyyy/mm/dd'; 
    settings.DateSeparator := '/'; 
    MyString := '2011/15/15'; 
    if TryStrToDateTime(MyString, MyDate, settings) then 
    Label1.Caption := 'correct date' 
    else 
    Label1.Caption := 'incorrect'; 
end; 
+0

非常感谢。 –

+0

注意:“如果S仅包含两个数字,则将其解释为当前年份的日期(m/d或d/m)。”所以,可以通过验证而不是格式良好的字符串。另外,时间部分也会通过。此外,功能跳过了领先的空间,给予更多的误报。 –

+0

只分配设置记录的两个字段可能会很危险。我可能会尝试从当前活动的设置首先初始化它:settings:= TFormatSettings.Create(GetUserDefaultLCID); – dummzeuch

2

使用带有TFormatSettings参数的重载版本的StrToDate()。然后,您可以传递所需的格式字符串进行解析,并且在验证分析的值之后它将返回一个TDateTime。

0

试图做同样的事情,碰到这个古老的线程运行。我最终写了自己的功能,并认为我会发布它。这个怎么样?

function IsValidDate(const S: string): boolean; 
var TestDate : tdatetime; 
begin 
Result := False; 

if (LastDelimiter('/',S) >= 4) 
and 
(Length(S)-LastDelimiter('/',S) >= 4) 
then 

    Result := TryStrToDate(S,TestDate); 

end; 

首先,我检查,看看是否在第二分隔符(/)至少在那里远远不够,既代表了一天一个月(第4位)。然后我用下一行强制一个4位数的年份。将第二个测试更改为> = 2为两位数,但我只是想知道,强制四位数字的年份并没有那么糟 - 只有两个笔画。

最后,我用TryStrToDate试验(+)。如果只有一个分隔符,或者它不是有效的日期,它将在这里被捕获。

如果你想获得幻想,你可以检查的一年是在过去10年或东西之内为好。只需添加:

Result := Result and (Now - TestDate < 3650); 

戴夫