Подтвердите реальную дату - PullRequest
2 голосов
/ 05 ноября 2011

Существует ли какая-либо функция, которая может проверять дату в формате aaaa / mm / gg (ccyy / mm / dd), возвращая True, если она действительна, или False в противном случае?Я имею в виду действительно правильную дату, а не только уровень до синтаксиса.

Ответы [ 4 ]

7 голосов
/ 05 ноября 2011

Год '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;
3 голосов
/ 05 ноября 2011

Это очень быстро, потому что сначала обнаруживаются самые простые ошибки.

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;
2 голосов
/ 05 ноября 2011

Используйте перегруженную версию StrToDate () с параметром TFormatSettings. Затем вы можете передать желаемую строку формата для анализа, и она вернет TDateTime после проверки проанализированных значений.

0 голосов
/ 12 ноября 2013

Попытка сделать то же самое и наткнулась на этот старый поток. Я закончил тем, что написал свою собственную функцию и думал, что я отправлю это. Как насчет этого?

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);

Dave

...