Answer the question
In order to leave comments, you need to log in
How to extract date from text?
I am writing a robot that recognizes speech. The robot asks the person for the date of birth, you need to recognize it. Phrases can be:
"I was born on June 2, 1745" (06/02/1745)
"date February 3, 94" (02/03/1994)
"24 0 5 1996" (05/24/1996)
"0 6 12 78" (12/06/1978)
"7 8 94" (08/07/1994)
Are there any ready-made solutions for this task? I think here you can easily do without neural networks. Naturally, the question is how to get the date from the processed text string, and not translate, recognize speech, etc.
Answer the question
In order to leave comments, you need to log in
I wrote a php function that solves my problem without neural networks. There are date variants that cannot be uniquely recognized, then two date variants are returned.
function dateBirth($inputString){
$inputString = str_replace(" январ", " 01", $inputString);
$inputString = str_replace(" феврал", " 02", $inputString);
$inputString = str_replace(" март", " 03", $inputString);
$inputString = str_replace(" апрел", " 04", $inputString);
$inputString = str_replace(" май", " 05", $inputString);
$inputString = str_replace(" мая", " 05", $inputString);
$inputString = str_replace(" мае", " 05", $inputString);
$inputString = str_replace(" июн", " 06", $inputString);
$inputString = str_replace(" июл", " 07", $inputString);
$inputString = str_replace(" август", " 08", $inputString);
$inputString = str_replace(" сентябр", " 09", $inputString);
$inputString = str_replace(" октабр", " 10", $inputString);
$inputString = str_replace(" ноябр", " 11", $inputString);
$inputString = str_replace(" декабр", " 12", $inputString);
$inputString = preg_replace('/\D/', '', $inputString);
$year = "error";
$daymonth = "";
// Если длина строки больше 8 или меньше 4, вычислить дату не сможем
if(strlen($inputString) < 4 || strlen($inputString) > 8){
return false;
}
if(strlen($inputString) >= 6){ // если длина больше или равна 6, то год равен 4 числам
if(intval(substr($inputString, -4)) > 1920){ //4 последних числа должны быть больше 1920, иначе это не год
$year = substr($inputString, -4);
$daymonth = substr($inputString, 0, -4);
}
if(strlen($inputString) == 6){ //если прошлое не год, значит год состоит из двух чисел, но тогда длина все строки не может быть длинее 6
if(intval("19".substr($inputString, -2)) > 1920){ //Проверяем, больше ли эти два числа чем 1920
$year = "19".substr($inputString, -2);
$daymonth = substr($inputString, 0, -2);
}
}
}
else{
if(intval("19".substr($inputString, -2)) > 1920){ //Если длина меньше 6, значит год из двух числел
$year = "19".substr($inputString, -2); //проверяем, больше ли год чем 1920
$daymonth = substr($inputString, 0, -2);
}
}
// ищем день и месяц
if($year != "error"){
if(strlen($daymonth) == 4 || strlen($daymonth) == 2){ //если деньмесяц состоит из 2 или 4 чисел. бьем строку пополам и получаем день + месяц
$day = substr($daymonth, 0, -strlen($daymonth)/2);
$month = substr($daymonth, -strlen($daymonth)/2);
}
// Если деньмесяц состоит из 3 чисел, то сложно
if(strlen($daymonth) == 3){
// Если первый 0, то день полюбому состоит из двух цифр
if(substr($daymonth, 0, 1) == "0"){
$day = substr($daymonth, 0, 2);
$month = substr($daymonth, -1);
}
// Если по середине 0, 1, 2 , то поулучается вилка, возвращаем сразу 2 вариианта
else if(substr($daymonth, 1, 1) == "0" || substr($daymonth, 1, 1) == "1" || substr($daymonth, 1, 1) == "2"){
$day = [substr($daymonth, 0, 1), substr($daymonth, 0, 2)]; //массив двух варантов дней
$month = [substr($daymonth, 1, 2), substr($daymonth, 2, 1)]; //массив двух вариантов месяцев
// проверяем, корректные ли дни и месяцы в массиве. Если нет, то превращаем массивы в немассивы без некорректных данных. Чтобы этим способом не проверить немассив, проверяем, массив ли это
if((intval($day[0]) > 31 || intval($month[0]) > 12 || intval($day[0]) == 0 || intval($month[0]) == 0) && is_array($day) && is_array($month)){
$day = $day[1];
$month = $month[1];
}
if((intval($day[1]) > 31 || intval($month[1]) > 12 || intval($day[1]) == 0 || intval($month[1]) == 0) && is_array($day) && is_array($month)){
$day = $day[0];
$month = $month[0];
}
}
// Если по середине 3
else if(substr($daymonth, 1, 1) == "3" && (substr($daymonth, 2, 1) == "1" || substr($daymonth, 2, 1) == "0")){
$day = [substr($daymonth, 0, 1), substr($daymonth, 0, 2)]; //массив двух варантов дней
$month = [substr($daymonth, 1, 2), substr($daymonth, 2, 1)]; //массив двух вариантов месяцев
// проверяем, корректные ли дни и месяцы в массиве. Если нет, то превращаем массивы в немассивы без некорректных данных. Чтобы этим способом не проверить немассив, проверяем, массив ли это
if((intval($day[0]) > 31 || intval($month[0]) > 12 || intval($day[0]) == 0 || intval($month[0]) == 0) && is_array($day) && is_array($month)){
$day = $day[1];
$month = $month[1];
}
if((intval($day[1]) > 31 || intval($month[1]) > 12 || intval($day[1]) == 0 || intval($month[1]) == 0) && is_array($day) && is_array($month)){
$day = $day[0];
$month = $month[0];
}
}
// Теперь просто двигаем точку с одного места ну другое проверяя, меньше ли день 31 и месяц 12. Если попали то круть
else{
// проверяем корректность данных при передвижении
if(intval(substr($daymonth, 0, 2)) <= 31 && intval(substr($daymonth, 0, 2)) != 0){
$day = substr($daymonth, 0, 2);
$month = substr($daymonth, -1);
}
// проверяем корректность данных при передвижении
else if(intval(substr($daymonth, 1, 2)) <= 12 && intval(substr($daymonth, 1, 2)) != 0 ){
$day = substr($daymonth, 0, 1);
$month = substr($daymonth, 1, 2);
}
else{
$day = "error";
$month = "error";
}
}
}
}
$dataBorn = "";
$format = 'd.m.Y';
// Если в итоге у нас вернулось 2 варианта даты, работаем с ним
if(is_array($day) && is_array($month)){
$dataBorn = [$day[0].".".$month[0].".".$year , $day[1].".".$month[1].".".$year];
$date = [];
// пробуем законвертить дату и добавиить в массив, если не получается, значит хуевая дата
try{
array_push($date, date_create_from_format($format, $dataBorn[0])->format('d.m.Y'));
// дополнительно проверяем на ошибки дату Например при конвертациии раньше 31.02.2016 выдавал не ошибку а 02.03.2016
if(DateTime::getLastErrors()['warning_count'] > 0) {
$date = "error";
}
}
catch (Error $e) {
$date = "error";
}
// пробуем законвертить дату и добавиить в массив, если не получается, значит хуевая дата
try{
array_push($date, date_create_from_format($format, $dataBorn[1])->format('d.m.Y'));
// дополнительно проверяем на ошибки дату Например при конвертациии раньше 31.02.2016 выдавал не ошибку а 02.03.2016
if(DateTime::getLastErrors()['warning_count'] > 0) {
$date = "error";
}
}
catch (Error $e) {
$date = "error";
}
// Проверяем, остался ли массив после предыдущих манипуляций, и если в нем всего одно значение, переделываем массив в строку
if(is_array($date) && count($date) < 2){
$date = $date[0];
}
return $date;
}
// Если вернулась всего одна дата
else{
// Проверяем на корректность день месяц
if(intval($day) > 31 || intval($month) > 12 || intval($day) == 0 || intval($month) == 0){
$day = "error";
$month = "error";
}
$dataBorn = $day.".".$month.".".$year;
// Продуем законвертииться в дату, если не получиилось, хуевая дата
try {
$date = date_create_from_format($format, $dataBorn)->format('d.m.Y');
// дополнительно проверяем на ошибки дату Например при конвертациии раньше 31.02.2016 выдавал не ошибку а 02.03.2016
if(DateTime::getLastErrors()['warning_count'] > 0) {
$date = "error";
}
}
catch (Error $e) {
$date = "error";
}
return $date;
}
}
dateBirth("текст текст текст 29.6.95 текст")
parse syntactically correct dates - Carbon::parse
and parse
"I was born on June 2, 1745" (06/02/1745)
"date February 3, 94" (02/03/1994)
"24 0 5 1996" (05/24/1996)
"0 6 12 78 "(12/06/1978)
" 7 8 94 "(08/07/1994)
without a neural network it is unlikely to work out
02/03/19
- what's this?
March 2, 2019 ?
February 3, 2019 ?
March 19, 2002 ?
a 02-03-19
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question