2011-11-05 64 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); 

戴夫