Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Как преобразовать строку в дату (2) ?

Delphi , Синтаксис , Дата и Время

Код распознаёт и русский и английский языки. Кстати вполне корректно обрабатывает и падежи типа:
 
2 мая 2002
май месяц 1999 года, 3е число
3е мая 1999 года
Солнечный апрельский день в 1998м году, 20е число
 
Корректно распознаёт что-нибудь типа
 
July 3, 99
 
но естественно не способен распознать
 
01-jan-03
 
т.е. год если двузначный, то должен быть больше 31. Иначе необоходим дополнительный параметер, указывающий годом считать первую или вторую найденную цифру в строке
 
Code:
 
Function StringToDate(Temp:String):TDateTime;
{©Drkb v.3(2007): www.drkb.ru,
®Vit (Vitaly Nevzorov) - nevzorov@yahoo.com}
type TDateItem=(diYear, diMonth, diDay, diUnknown);
      TCharId=(ciAlpha, ciNumber, ciSpace);
 
//языковые настройки. Для включения нового языка добавляем раскладку сюда, дополняем тип alpha и меняем
//единственную строку где используется эта константа
const
   eng_monthes:array[1..12] of string=('jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec');
   rus_monthes:array[1..12] of string=('янв', 'фев', 'мар', 'апр', 'ма', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дес');
   alpha:set of char=['a'..'z','а'..'я'];
 
//временные переменные
var month, day, year:string;
     temp1:string;
     i, j:integer;
     ci1, ci2:TCharId;
 
Function GetWord(var temp:string):string;
begin
   //возвращаем следующее слово из строки и вырезаем это слово из исходной строки
   if pos(' ', temp)>0 then
     begin //берём слово до пробела
       result:=trim(copy(temp, 1, pos(' ', temp)));
       temp:=copy(temp, pos(' ', temp)+1, length(temp));
     end
   else //это последнее слово в строке
     begin
       result:=trim(temp);
       temp:='';
     end;
end;
 
Function GetDateItemType(temp:string):TDateItem;
   var i, j:integer;
begin
   //распознаём тип слова
   i:=StrToIntDef(temp,0); //попытка преобразовать слово в цифру
   Case i of
     0: Result:=diMonth; //не число, значит или месяц или мусор
     1..31:Result:=diDay;//числа от 1 до 31 считаем днём
     else Result:=diYear;//любые другие числа считаем годами
   End;
end;
 
Function GetCharId(ch:char):TCharId;
begin
   //узнаём тип символа, нужно для распознавания "склееных" дней или лет с месяцем
   Case ch of
    ' ':Result:=ciSpace;
    '0'..'9':Result:=ciNumber;
    else Result:=ciAlpha;
   End;
end;
 
 
 
begin
temp:=trim(ansilowercase(temp));
month:='';
day:='';
year:='';
//замена любого мусора на пробелы
For i:=1 to length(temp) do
   if not (temp[i] in alpha+['0'..'9']) then temp[i]:=' ';
 
//удаление лишних пробелов
while pos('  ', temp)>0 do
   Temp:=StringReplace(temp, '  ',' ',[rfReplaceAll]);
 
//вставка пробелов если месяц слеплен с днём или годом
ci1:=GetCharId(temp[1]);
i:=1;
Repeat
   inc(i);
   ci2:=GetCharId(temp[i]);
   if ((ci1=ciAlpha) and (ci2=ciNumber)) or ((ci1=ciNumber) and (ci2=ciAlpha)) then
     insert(' ', temp, i);
   ci1:=ci2;
Until i>=length(temp);
 
//собственно парсинг
while temp>'' do
   begin
     temp1:=GetWord(temp);
     Case GetDateItemType(temp1) of
       diMonth: if month='' then //только если месяц ещё не определён, уменьшает вероятность ошибочного результата
                  for i:=12 downto 1 do // обязателен отсчёт в обратную сторону чтоб не путать май и март
                    if (pos(eng_monthes[i],temp1)=1) or (pos(rus_monthes[i],temp1)=1) then //сюда добавляем ещё язык если надо
                      month:=inttostr(i);
       diDay:   Day:=temp1;
       diYear:  Year:=temp1;
     End;
   end;
 
 
//проверка - все ли элементы определены
if (month='') or (Day='') or (Year='') then raise Exception.Create('Could not be converted!');
 
//поправка на двузначный год
if length(year)<3 then year:='19'+year;
 
//кодирование результата
Result:=EncodeDate(Strtoint(Year), Strtoint(month), Strtoint(Day));
end;

Автор: Vit (www.delphist.com, www.drkb.ru, www.unihighlighter.com, www.nevzorov.org)

Функция StringToDate предназначена для преобразования строкового представления даты в значение типа TDateTime. Функция использует различные техники, такие как парсинг слов, проверка типа символов и сравнение строк, чтобы идентифицировать месяц, день и год в входной строке.

Некоторые ключевые моменты о том, как работает эта функция:

  1. Она сначала конвертирует входную строку в нижний регистр для упрощения процесса сравнения.
  2. Затем она удаляет любые неалфавитные символы из входной строки, заменяя их пробелами.
  3. Функция затем проверяет слова, соответствующие месяцам (например, "янв", "фев", и т.д.), и обновляет переменную month соответственно.
  4. Она также проверяет числовые значения, которые могут быть днями или годами, и обновляет переменные day или year соответственно.
  5. После парсинга всех компонентов даты функция строит значение типа TDateTime с помощью функции EncodeDate.

Один возможный улучшение этой функции заключается в добавлении поддержки более форматов дат, таких как ISO 8601 (например, "2022-07-03") или даже даты в формате "MM/DD/YYYY" или "YYYY-MM-DD". Это могло бы включать добавление дополнительной логики парсинга и использование регулярных выражений для соответствия конкретным шаблонам.

Еще один потенциальный улучшение заключается в том, чтобы сделать функцию более устойчивой к ошибкам, например, пустым входными строками или недопустимыми форматами дат. Например, если входная строка не содержит допустимого формата даты, функция могла бы выбросить исключение вместо возвращения значения по умолчанию.

Вот обновленная версия функции StringToDate, которая включает некоторые из этих улучшений:

function StringToDate(Temp: string): TDateTime;
var
  month, day, year: string;
  temp1: string;
  i, j: integer;
  ci1, ci2: TCharId;
begin
   // Convert input string to lowercase and remove non-alphanumeric characters
  Temp := trim(ansilowercase(Temp));

   // Check for ISO 8601 date format (e.g., "2022-07-03")
  if Pos('-', Temp) > 0 then
    begin
      year := Copy(Temp, 1, Pos('-', Temp) - 1);
      day := Copy(Temp, Pos('-', Temp) + 1, Pos('-', Temp) + 3 - Pos('-', Temp));
      month := Copy(Temp, Pos('-', Temp) + 4, Length(Temp));

       // Convert ISO date format to TDateTime
      Result := EncodeDate(StrToInt(year), StrToInt(month), StrToInt(day));
    end
    else
      begin
         // Parse non-ISO date formats (e.g., "July 3, 1999")
        month := '';
        day := '';
        year := '';

        while Temp > '' do
          begin
            temp1 := GetWord(Temp);
            Case GetDateItemType(temp1) of
              diMonth: if month = '' then
                for i := 12 downto 1 do
                  if (Pos(eng_months[i], temp1) = 1) or (Pos(rus_months[i], temp1) = 1) then
                    month := IntToStr(i);
              diDay: day := temp1;
              diYear: year := temp1;
            End;
          end;

         // Convert parsed date components to TDateTime
        Result := EncodeDate(StrToInt(year), StrToInt(month), StrToInt(day));
      end;
end;

В этой обновленной версии функция сначала проверяет, есть ли в входной строке формат ISO 8601 (например, "2022-07-03"), и если да, то преобразует его в значение типа TDateTime. Если нет, она переходит к парсингу не-ISO форматов дат с помощью той же логики, что и раньше.

Статья описывает функцию для преобразования строки в дату, которая может распознавать месяцы на русском и английском языках, а также корректно обрабатывать падежи типа 'май месяц 1999 года, 3е число'. Функция работает с кодом на Delphi.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Дата и Время ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-05-01 14:28:51/0.0066680908203125/1