验证真正的约会
这是非常快的,因为最简单的错误首先被捕获。
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;
是 '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;
非常感谢。 –
注意:“如果S仅包含两个数字,则将其解释为当前年份的日期(m/d或d/m)。”所以,可以通过验证而不是格式良好的字符串。另外,时间部分也会通过。此外,功能跳过了领先的空间,给予更多的误报。 –
只分配设置记录的两个字段可能会很危险。我可能会尝试从当前活动的设置首先初始化它:settings:= TFormatSettings.Create(GetUserDefaultLCID); – dummzeuch
使用带有TFormatSettings参数的重载版本的StrToDate()。然后,您可以传递所需的格式字符串进行解析,并且在验证分析的值之后它将返回一个TDateTime。
试图做同样的事情,碰到这个古老的线程运行。我最终写了自己的功能,并认为我会发布它。这个怎么样?
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);
戴夫
对不起,Andreas。 :)这工作(所以没有downvote),但提问者使用XE2。更好的答案是使用'TFormatSettings'的@Arjen。不过,我会允许这个异常,而不是像Arjen那样使用'TryStrToDate'。 –
@Ken,谢谢。关于例外:取决于具体情况。 安德烈亚斯,并没有downvote从我。 –
'StrToDate(S,Format)'方式不是XE2特有的,但不够严格。正。而且我认为真正的downvoter试图架设某人。 –