Дата рождения с помощью регулярных выражений

Невский

Новичок
Дата рождения с помощью регулярных выражений

В тексте пользователь может указать день рождения всякими способами, наиболее часто встречается такой вид:


Дата рождения 25 сентября 1964 г.
Дата рождения 3 марта 1981год
Дата рождения 17 июля 1979 года
Дата рождения 10 января 1960 года.
Дата рождения 11.10.1978г.
Дата рождения – 19.03.1966 г.
Дата рождения 18.06.1982г
Дата рождения 29 сентября 1982г.(полных 26 лет)
Дата рождения 27.10.1972
Дата рождения 21 декабря 1983г.
Дата рождения 09.03.1980г., 29 лет
Дата рождения 05. 12. 1983г.
Дата рождения 15.08.83г.
Дата рождения 1956-06-13


Как с помощью регулярных выражений, вычленить год рождения из строки и привести его в вид ДД.ММ.ГГГГ ?
Алгоритм, который крутится у меня в мыслях, на мой взгляд может получиться очень громоздким. Может есть уже готовые решения?

Заранее спасибо.
 

dimagolov

Новичок
Невский, а как однозначно решить 11.10.1978г. это 10 ноября или 11 октября?
 

Фанат

oncle terrible
Команда форума
можно принять соглашение, что это 11 октября.
хотя, конечно, жестко задать формат ввода было бы лучше
вообще странная задача для _веб_ приложения.

-~{}~ 16.03.09 15:30:

но рег написать, пожалуй, можно.
принять формат дмг и что-то вроде \d [alnum] \d
а месяц потом дополнительно разбирал.
 

DiMA

php.spb.ru
Команда форума
странно, почему ;№(?%:! тему за взлом и варез не закрыл? .-)
 

Royal Flash

-=MaestrO=-
Невский
Из таких данных нельзя с точностью узнать дату никаким способом, так как:
а как однозначно решить 11.10.1978г. это 10 ноября или 11 октября?
или 02.03.01 :)

Поэтому - либо изначально запрашивать данные в определенном формате или отказаться от этой идеи вообще.
 

Невский

Новичок
Автор оригинала: findnext
http://regexlib.com/ тут можно найти всякие решения
Поищу, но хотелось бы по-русски сначала...

-~{}~ 16.03.09 20:13:

Автор оригинала: *****
чо - правда так пишут?
В основном, те, кто такого возраста, бывает.

-~{}~ 16.03.09 20:14:

Автор оригинала: dimagolov
Невский, а как однозначно решить 11.10.1978г. это 10 ноября или 11 октября?
Наши конечно же пишут сначала день, потом месяц, значит 11 октября

-~{}~ 16.03.09 20:16:

Автор оригинала: *****
можно принять соглашение, что это 11 октября.
хотя, конечно, жестко задать формат ввода было бы лучше
вообще странная задача для _веб_ приложения.
дело в том что обрабатываются обычные файлы различных форматов с помощью php, в дальнейшем все бедет в веб...

-~{}~ 16.03.09 20:19:

Автор оригинала: Royal Flash
Невский
Из таких данных нельзя с точностью узнать дату никаким способом, так как:


или 02.03.01 :)

Поэтому - либо изначально запрашивать данные в определенном формате или отказаться от этой идеи вообще.
Формат однозначно сначала день, потом месяц, потом год или наоборот, год, месяц, день (но это один случай из 1000, можно не учитвать).
 

dimagolov

Новичок
Формат однозначно сначала день, потом месяц, потом год или наоборот, год, месяц, день (но это один случай из 1000, можно не учитвать).
поржал :D
Невский, ты понимаешь, что без знания формата ввода для каждого конкретного случая задача решения не имеет? ты определись в начале в каждом конкретном источники данные в одинаковом формате или винегрет? если в одинаковом, то можно делать предположения, если винегрет то решения нету.
 

Невский

Новичок
Автор оригинала: dimagolov
поржал :D
Невский, ты понимаешь, что без знания формата ввода для каждого конкретного случая задача решения не имеет? ты определись в начале в каждом конкретном источники данные в одинаковом формате или винегрет? если в одинаковом, то можно делать предположения, если винегрет то решения нету.
На то они и регулярные выражения, чтобы все привести к одному формату. Дату рождения можно записать максимум 20 вариантами, вот эти варианты и нужно прописать. Хорошо смеется тот, кто смеется последним...
 

x-yuri

Новичок
Невский, ты понимаешь, что без знания формата ввода для каждого конкретного случая задача решения не имеет? ты определись в начале в каждом конкретном источники данные в одинаковом формате или винегрет? если в одинаковом, то можно делать предположения, если винегрет то решения нету.
dimagolov задача вполне решаема, если не надо угадывать ДД-ММ или ММ-ДД. Другое дело, что если это форма в вебе, то лучше имхо фиксированный формат (может с небольшими вариациями) + каледнарь (выбор мышкой), а то и просто календарь без поля ввода

Алгоритм, который крутится у меня в мыслях, на мой взгляд может получиться очень громоздким
Невский, покажи
 

Невский

Новичок
Нет, планируется обработка вородовских файлов.

Алгоритм примерно такой:
Начало даты обязательно состоит из 2-х (или 1) цифры, если за цифрами идет точка (слеш), то месяц скорее всего также из 2-х цифр (крайний случай из 1), далее после точки год, обычно 4 цифры (но может быть и 2)
Если после даты идет пробел и буква, то значит месяц буквенный (можно определить другой функцией), а далее год. Конечно же можно предугадать вариант, что сначала идет год.
Вот вкратце и все.

-~{}~ 17.03.09 00:46:

PHP:
if (preg_match('/((Дата рождения.?\s)([\d]+)\s*(([\а-яё*]+)|(\.[\d]+\.))\s*([\d]+))/i', $content, $dd))  
{echo "Дата такая <b>$dd[0]</b>";}  
else
{echo "Даты нет";}
Набросал выражение, если чуть доработать, то будет всевозможные варианты проверять (имеется ввиду вместо точек тире, слеши и пр.), а также можно дописать выражение, если дата начинается с года. Теперь осталось написать функцию, которая будет переводить в необходимый вид. Меня интересует правильно ли я составил выражение, нет ли в нем чего лишнего?
 

x-yuri

Новичок
1) что значит .?\s
2) зачем Дата рождения.?\s взято в скобки
3) чем отличается [\d] от \d
4) что значит \a
5) зачем * в [\а-яё*]
6) зачем \.[\d]+\. взято в скобки
ну и да, доработать надо немного
 

Невский

Новичок
Автор оригинала: x-yuri
1) что значит .?\s
2) зачем Дата рождения.?\s взято в скобки
3) чем отличается [\d] от \d
4) что значит \a
5) зачем * в [\а-яё*]
6) зачем \.[\d]+\. взято в скобки
ну и да, доработать надо немного
Вот если бы я знал, в каких случаях, что делать, нужно потренировтаься на примерах.
по п. 1 подразумевал, что слово "Дата рождения" может быть написано с двоеточием ":" или без него, после него идет пробел (которого теоретически может и не быть) . Как по другому записать?
по п. 2 можно без скобок?
по п. 3 т.е. \d можно записать без [] ?
по п. 4 скорее всего я сначала писал \w а потом решил сократить условие, слеш и остался.
по п. 5 * наверное осталось от \w*
Плохо когда не знаешь как правильно :confused: вот и делаешь все методом "научного тыка" :)

Спасибо за правку кода, буду править и тестировать.
 

Невский

Новичок
Сделал так
PHP:
if (preg_match('/((Дата рождения|Дата и место рождения|Год и место рождения|Год рождения|Родилась|Родился).?\s*?(\d+\.?)\s*?(([а-яё]+)|(\d+\.?))\s*?(\d+))/i', $content, $dd))  
{echo "Дата такая <b>$dd[0]</b><br>";}  
else  
{echo "Даты нет<br>";}
Для 95% задач достаточно, а там время подскажет, что где улучшить, чтобы дойти до 100%

-~{}~ 17.03.09 13:25:

А сейчас вот думаю, что все таки важно слово "рождения", значит вот этот отрезок "Дата рождения|Дата и место рождения|Год и место рождения|Год рождения" можно заменить просто на "рождения"
 

x-yuri

Новичок
.?\s*? - не вижу смысла в '?' (как и в остальных случаях применения \s*?), но я имел в виду .?\s -> .*? (но так не стоит делать если слово рождение может упоминаться раньше в тексте)

(\d+\.?) -> (\d+)\.? - зачем удалять точку потом в коде, если ее можно просто не захватывать в подшаблон

А сейчас вот думаю, что все таки важно слово "рождения", значит вот этот отрезок "Дата рождения|Дата и место рождения|Год и место рождения|Год рождения" можно заменить просто на "рождения"
тебе виднее. Думаю разумно исходить из того, что есть на данный момент (я так понял есть набор файлов с информацией, откуда надо эти даты извлекать), т.е. простейший шаблон подходящий для этих файлов. А редкие случаи учитывать по мере их появления
 

yok

Новичок
Такое дело, везде вижу "дата рождения" пишется первой, тоесть если в пхп работает то
(?<=ата рождения)([\w\s]+)((?<=г.\s)|(?<=года.))
Это не решение, это направление, позиционно вычленить дату, и уже далее работать.
 

Beavis

Banned
Невский
ну так напиши для каждого случая регулярку и всё
 
Сверху