Hi everyone,

I'm pretty new here, though I've read many posts here:)

I got into a question and thought someone might be able to help me with it.
I need to read human language date input and extract the date from an input.

Let me explain:
Lets say we have this text "I should go home tomorrow 3:20pm"
I need php to give me date/time of when he should go home.
So, if its 16/09/2009, it shows 17/09/2009 3:20pm

Is there anyway someone can help me with this? would really appreciate it.
Thanks
Sina

Recommended Answers

All 28 Replies

Although I myself haven't really played with this feature, the problem is the server time does not match your local time. In other words the server is in a different timezone to where you live. To solve this read the first few screens on the page at http://www.php.net/manual/pl/function.date-default-timezone-set.php

Hey,

Have you tried using the strtotime method... e.g.

date('d-m-Y h:ia', strtotime("tomorrow at 3:30pm") ) ;

R.

Thank you for your replies guys.

cwarn23, I think you didn't read/understand my post. please read it again. sorry.

robothy, Thanks. Yes, I know strtotime, but what I want is a bit complex.

I have a text lets say "I should go home and get my keys tomorrow 2:48pm".
So it is not just "tomrrow 2:48pm" that php would understand.
It is the whole text. How should I extract the time from the text and pass it to php?

And since many visitors are going to use it, I want to have something flawless, so no problem should happen for anyone and if any problem happen, I want the system to skip inserting time instead of showing errors. Any solution for that too?

Will really appreciate replies.
Thanks a lot

Member Avatar for diafol

Have a set of words to replace with dates, e.g.

$rep['tomorrow'] = date('your format here',mktime(0, 0, 0, date("m"), date("d")+1, date("y"));

explode your string into $wordarray array and if that word has a $rep key, do a replace. Ensure you have

foreach ($wordarray as word){

if(isset($rep[$word])){
   $string = str_ireplace($word,$rep[$word],$string);
}
}

The str_ireplace is not case-sensitive so it will replace TOMORROW, Tomorrow and all permutations. It won't account for spelling mistakes of course.

An easier option is as follows:

<?
$time='3:30pm';
//set variable above
//do not change below


$time=strtolower($time);
$var=explode(':',$time);
if (substr_count($var[1],'pm')) {
$var[1]=str_replace(array('pm','am'),'',$var[1]);
$var[0]+=12;
} else {
$var[1]=str_replace(array('pm','am'),'',$var[1]);
}
echo date('d-m-Y h:ia', strtotime('tomorrow '.$var[0].':'.$var[1].':00') ) ;
?>
Member Avatar for diafol

Yeah fair one c, but will that replace tomorrow in any part of the sentence? What if it was "... tomorrow before 3.30pm"?

My code works for any time of the day! Just as long as the variable $time on line 1/2 has the same formatting.

Thanks a lot guys so far.

Now few questions.
How to find time in the text?
As I said, what method to use for getting time out of this text "I should go to doctor tomrrow 5:42pm."

What I do first is to remove "." Then Looking for word tomorrow, today, ...
Then how to find the time? it can be with or without am/pm. it can be 4 digit military like numbers 1103 ,etc.
Can someone write a code for the text above? Or help me write the code?
I will also add urgency detection to the text, so, must, should, may, etc. will have different urgencies.

And it is very important for me to finish something that can accurately get the time.
Will really appreciate more help.
(and thanks a lot again for the help so far :) )

Try this:

<?
$string="I should go to doctor tomrrow 5:42pm.";
//set variable above
//don't change below.

preg_match_all('/^(.*|)([0-9]+\:[0-9]+[a-zA-Z][a-zA-Z])(.*|)$/',$string,$time);
$time=$time[2][0];
$time=strtolower($time);
$var=explode(':',$time);
if (substr_count($var[1],'pm')) {
$var[1]=str_replace(array('pm','am'),'',$var[1]);
$var[0]+=12;
} else {
$var[1]=str_replace(array('pm','am'),'',$var[1]);
}


echo date('d-m-Y h:ia', strtotime('tomorrow '.$var[0].':'.$var[1].':00') ) ;
?>

cwarn23, May I ask what is the function of $time=$time[2][0]; in the code?
would appreciate your reply.
And guys, what about date? like the input be "I should go home 21/08/09 2:11pm" or any other date format like january, 12/02 , etc.

Thanks

cwarn23, May I ask what is the function of $time=$time[2][0]; in the code?

Well the code $time=$time[2][0]; clears some of the memory while leaving the required data in a variable called time. The array $time=$time[2][0]; was output by preg_match_all().

I understand that, but what I mean is that why "[2][0]" ? what is stored there? Can you explain a bit about this preg_match_all ? cause I might need to use another regular expressions.

And there is a problem now with the code. it cannot detect 3:21 pm.(space after time), which is because of the regex. Any solution?
And what about the date btw? :)

Thanks again
Sina

Try this:

<?
$string="I should go to doctor tomrrow 5:42 pm.";
//set variable above
//don't change below.

preg_match_all('/^(.*|)([0-9]+\:[0-9]+([^a-zA-Z]+|)[a-zA-Z][a-zA-Z])([^a-zA-Z].*|)$/',$string,$time);
$time=str_replace($time[3][0],'',$time[2][0]);
$time=strtolower($time);
$var=explode(':',$time);
if (substr_count($var[1],'pm')) {
$var[1]=str_replace(array('pm','am'),'',$var[1]);
$var[0]+=12;
} else {
$var[1]=str_replace(array('pm','am'),'',$var[1]);
}


echo date('d-m-Y h:ia', strtotime('tomorrow '.$var[0].':'.$var[1].':00') ) ;
?>

Also as for how the array works, basically the first number in the array for preg_match_all displays what number bracket starting from the beginning it should display (starting from 1). Also then second number which I kept zero is what number match to display. Hope that helps.

Thanks for the reply. I ran a print_r and it shows:

Array ( [0] => Array ( [0] => *my text here* ) [1] => Array ( [0] => *text without time* ) [2] => Array ( [0] => *Only time* ) [3] => Array ( [0] => ) [4] => Array ( [0] => ) )
And it seems [3][0] and [4][0] are empty.

Now about the code.
It works for "I should go home 2:31pm" or "I should go home 2:31 pm" but it doesn't work with 2pm, 2:21, etc.
It needs AM or PM to be there. any way to solve the issue?

And two more questions. What about Dates? how to find and parse them? And another question is that, if two times be entered, why preg_match_all only assigns the last time only? (for example if the text be "go home 2:21pm or 3:11pm" it only parses 3:11pm. my question is why it doesn't parse 2:21pm ?)

Thanks a lot :) again and again

Any more help? :(

Still looking for help :(
Guys, please...

Sorry about the late reply but I have been really busy. Your code should look something like the following:

<?
$string="I should go to doctor tomrrow 5 am.";
//set variable above
//don't change below.
 
preg_match_all('/^(.*|)(([0-9]+\:[0-9]+|[^0-9:][0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z])([^a-zA-Z].*|)|'.
'(([0-9]+\:[0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)))$/',$string,$time);
$timeb=$time[3][0];
$var=explode(':',$timeb);
if (!isset($var[1]) || empty($var[1])) {
    $var[1]=0;
    }
if ($time[5][0]=='pm') {
$var[0]+=12;
}
 
echo date('d-m-Y h:ia', strtotime('tomorrow '.$var[0].':'.$var[1].':00'));
?>

Hope that helps.

Thanks a lot for the new code.

It now can read 3pm and 3:21pm.
The problem is that if the time be 21:21 or 11:32, it cannot read it.
Is there any way to do that?

btw, I am going to put your name inside the code if you don't mind as a contributor :) (unfortunately I cannot tell anyone here yet what is the project as it is secret until it gets released.)

Would really appreciate if you can help me getting this to a complete level being able to read all times.
Thanks a lot.

As simular as the code may look try the following:

<?
$string="I should go to doctor tomrrow 5:30.";
//set variable above
//don't change below.
 
preg_match_all('/^(.*|)(([0-9]+\:[0-9]+|[^0-9:][0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)|'.
'(([0-9]+\:[0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)))$/',$string,$time);
$timeb=$time[3][0];
$var=explode(':',$timeb);
if (!isset($var[1]) || empty($var[1])) {
    $var[1]=0;
    }
if ($time[5][0]=='pm') {
$var[0]+=12;
}
 
echo date('d-m-Y h:ia', strtotime('tomorrow '.$var[0].':'.$var[1].':00'));
?>

Hey, thanks for the reply.

Its working with 3:30 now. but there is still a problem. it counts 13:30 as 3:30 (does not understand 13:30).
Is it possible to make the system understand if its 13:30 or 3:30 ?

Thanks a lot again

Try this:

<?
$string="I should go to doctor tomrrow 13:30.";
//set variable above
//don't change below.
 
preg_match_all('/^(.*[^0-9]|)(([0-9]+\:[0-9]+|[^0-9:][0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)|'.
'(([0-9]+\:[0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)))$/',$string,$time);
$timeb=$time[3][0];
$var=explode(':',$timeb);
if (!isset($var[1]) || empty($var[1])) {
    $var[1]=0;
    }
if ($time[5][0]=='pm') {
$var[0]+=12;
}
 
echo date('d-m-Y h:ia', strtotime('tomorrow '.$var[0].':'.$var[1].':00'));
?>

Thanks a lot cwarn23 for the reply.

I have added a check for months and week days within the script.
and now it can read for example tomorrow 2:30pm.

Now there are few problems!
1- how to make it read for example 23 september 11:30pm ?
2- If you put the time 12:30pm, it makes the number 24:30:00 so, the script will set the time wrong.
3- If the day be entered without time, the system will go wrong. so, tomorrow will result in no date.

Would appreciate if you can help me with these. so this can be made a complete script :)
Thanks a lot so far.
Sina

Member Avatar for diafol

From what I can see the "+12" bit will result in 24:xx for certain times. Perhaps using the mktime() function would be better here. This takes "overflows" into account, so for example, if you add 12 hours to the 'hours' parameter already at say 12 hours, the date will adjust accordingly to the next day. Sorry to jump in.

I managed to implement the date into the script but still the error about 24:xx is still there. I think it is actually a bug with the strtotime function. But while I try and fix it the following will give you something to play around with.

<?
$string="I should go to doctor 23:30.";
//set variable above
//don't change below.
preg_match_all('/^(.*[^0-9]|)(([0-9]+\:[0-9]+|[^0-9:][0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)|'.
'(([0-9]+\:[0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)))$/',$string,$time);
$timeb=$time[3][0];
$var=explode(':',$timeb);
if (!isset($var[1]) || empty($var[1])) {
    $var[1]=0;
    }
if ($time[5][0]=='pm') {
$var[0]+=12;
}
//$var[0]-=1;
if (!preg_match_all('/(tomorrow|tomrrow|tomorrw|tomorow|[^0-9]([0-9][0-9]?|)[^0-9]?[^0-9]?[^0-9]?(\bjanuary\b|\bjan\b|\bfebruary\b|\bfeb\b|\bmarch\b|\bmar\b|\bapril\b|\bapr\b|\bmay\b|\bjune\b|\bjun\b|\bjuly\b|\bjul\b|\baugust\b|\baug\b|\bseptember\b|\bsep\b|\bsept\b|\boctober\b|\boct\b|\bnovember\b|\bnov\b|\bdecember\b|\bdec\b)[^0-9]?[^0-9]?[^0-9]?([0-9][0-9]|)[^0-9][^0-9]?[^0-9]?([0-9][0-9][0-9][0-9]|)[^:][^:])/i',$string,$dateresult)) {
    $date=date('j F Y').' '.$var[0].':'.$var[1].':00';
    } else {
    if ($dateresult[1][0]=='tomorrow' || $dateresult[1][0]=='tomrrow' || $dateresult[1][0]=='tomorrw' || $dateresult[1][0]=='tomorow') {
        $date='tomorrow';
        } else {
        $months=array('january'=>'January','jan'=>'January','february'=>'February','feb'=>'February','march'=>'March','mar'=>'March','april'=>'April','apr'=>'April','may'=>'May','june'=>'June','jun'=>'June','july'=>'July','jul'=>'July','august'=>'August','aug'=>'August','september'=>'September','sep'=>'September','sept'=>'September','october'=>'October','oct'=>'October','november'=>'November','nov'=>'November','december'=>'December','dec'=>'December');
        if (!empty($dateresult[4][0])) {
            $date=$dateresult[4][0];
            } else if (!empty($dateresult[2][0])) {
            $date=$dateresult[2][0];
            } else if (substr_count(strtolower(date('F')),strtolower($dateresult[3][0]))>0) {
            $date=date('j');
            } else {
            $date='1';
            }
        if (empty($dateresult[5][0])) {
            $year=date('Y');
            } else {
            $year=$dateresult[5][0];
            }
        $date.=' '.$months[strtolower($dateresult[3][0])].' '.$year.' '.$var[0].':'.$var[1].':00';
        }
    }
echo date('d-m-Y h:ia', strtotime($date));
?>

oh man, you made it so cool!
I used different method to get the month/date. but mine didn't support numbers before date. it seems you are a master of regex! the code is really cool :)

One thing I like to say is that, before I test it, I think if we change this part, the issue will be solved:
if (($time[5][0]=='pm') && ($var[0] != 12)) {
$var[0]+=12;
}
am I right?

Also I fixed that bug with the following:

<?
$string="I should go to doctor 12:30.";
//set variable above
//don't change below.
preg_match_all('/^(.*[^0-9]|)(([0-9]+\:[0-9]+|[^0-9:][0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)|'.
'(([0-9]+\:[0-9]+)([^a-zA-Z]+|)([a-zA-Z][a-zA-Z]|)([^a-zA-Z].*|)))$/',$string,$time);
$timeb=$time[3][0];
$var=explode(':',$timeb);
if (!isset($var[1]) || empty($var[1])) {
    $var[1]=0;
    }
if ($time[5][0]=='pm') {
$var[0]+=12;
}
$timestamp=0;
if ($var[0]>=24) {
    $var[0]-=1;
    $timestamp=3600;
    }
//$var[0]-=1;
if (!preg_match_all('/(tomorrow|tomrrow|tomorrw|tomorow|[^0-9]([0-9][0-9]?|)[^0-9]?[^0-9]?[^0-9]?(\bjanuary\b|'.
'\bjan\b|\bfebruary\b|\bfeb\b|\bmarch\b|\bmar\b|\bapril\b|\bapr\b|\bmay\b|\bjune\b|\bjun\b|\bjuly\b|\bjul\b|'.
'\baugust\b|\baug\b|\bseptember\b|\bsep\b|\bsept\b|\boctober\b|\boct\b|\bnovember\b|\bnov\b|\bdecember\b|\bdec\b)'.
'[^0-9]?[^0-9]?[^0-9]?([0-9][0-9]|)[^0-9][^0-9]?[^0-9]?([0-9][0-9][0-9][0-9]|)[^:][^:])/i',$string,$dateresult)) {
    $date=date('j F Y').' '.$var[0].':'.$var[1].':00';
    } else {
    if ($dateresult[1][0]=='tomorrow' || $dateresult[1][0]=='tomrrow' || $dateresult[1][0]=='tomorrw' || $dateresult[1][0]=='tomorow') {
        $date='tomorrow';
        } else {
        $months=array('january'=>'January','jan'=>'January','february'=>'February','feb'=>'February','march'=>'March',
        'mar'=>'March','april'=>'April','apr'=>'April','may'=>'May','june'=>'June','jun'=>'June','july'=>'July',
        'jul'=>'July','august'=>'August','aug'=>'August','september'=>'September','sep'=>'September','sept'=>'September',
        'october'=>'October','oct'=>'October','november'=>'November','nov'=>'November','december'=>'December','dec'=>'December');
        if (!empty($dateresult[4][0])) {
            $date=$dateresult[4][0];
            } else if (!empty($dateresult[2][0])) {
            $date=$dateresult[2][0];
            } else if (substr_count(strtolower(date('F')),strtolower($dateresult[3][0]))>0) {
            $date=date('j');
            } else {
            $date='1';
            }
        if (empty($dateresult[5][0])) {
            $year=date('Y');
            } else {
            $year=$dateresult[5][0];
            }
        $date.=' '.$months[strtolower($dateresult[3][0])].' '.$year.' '.$var[0].':'.$var[1].':00';
        }
    }
echo date('d-m-Y h:ia', ($timestamp+strtotime($date)));
?>

you tried to solve the time issue in a cool way :) fooling php :D

but just a question. when the time be entered as 12:30 pm, it will be equal to 12:30.
This script makes it 24:30. then takes the time back to 23:30. then moves the time to 00:30 of the day tomorrow.
I think the script should be somehow revised.

When someone enters 12:20am, 12:20 will be passed to the strtotime, so, it thinks the time is 12:20 while it is equal to 00:20.
and if he enters 12:20pm, 23:20 will be passed to the script, then an hour will be added. so it will be 00:20 of the next day.

So, I think the way I suggested will work better. and one line of code should be added for preventing 12:20am to be counted as 12:20pm.

And one more thing. How to add next saturday, next january, etc. to the script? strtotime supports weekdays for next. but I think it won't support months. can you add next functionality to the script? it would be amazing then.

And again, I have to thank you so much for your hard work and great help on this script. I really appreciate your help :)

Actually it doesn't add 12 hours in that situation because 12:00pm is midday just like 12:00am is just after midnight. Just how the system of time seems to work.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.