Although I now already have 2 working functions I thought I’d get on and really grok Anthony’s idea - he keeps putting this my way, and while I understand how it works, its not till you start playing with things you really deeply “grok it to its fullness”, anyhow I came up with this:
Use the interface and the collection from his code, but change the concrete classes to these:
class AmPmParser implements TimeConfobulator
{
public function accepts($subject){
preg_match_all('~((0|1)?[0-9])((a|p)m)~i', $subject, $parts);
if(5 !== count($parts) || empty( $parts[0] ) ){
return false;
}
return sprintf(
'%02s:00',
('pm' === strtolower($parts[3][0])) ? $parts[1][0] + 12 : $parts[1][0]
);
}
}
class DigitsOnlyParser implements TimeConfobulator
{
public function accepts($subject){
$subject = preg_replace('~\\D~', '', $subject);
preg_match_all('~^((0|1|2)?[0-9])([0-5][0-9])?$~i', $subject, $parts);
if( 4 !== count($parts) || empty( $parts[0] ) ){
return false;
}
$mins = $parts[3][0] ? $parts[3][0] : "00" ;
return sprintf(
'%02s:%02s' , $parts[1][0] , $mins
);
}
}
Then run the same tests on it like so;
$confobulator = new TimeConfobulatorCollection();
//2 test arrays
/** /
$times = array(
'19 30','0915','19.00','19:00',' 19 5 ', '12.15',
' 19 99 ', '19: 001', '75', 'aa' , '12pm' );
/**/
$times = array( '9','0915', '9.00','09:00',' 09 ',
' 9 90 ', '09: 001', '45:09', '9am:06' ,'-9-09');
/**/
var_dump( $times );
foreach( $times as $time ){
var_dump( $confobulator->addConfobulator(
new DigitsOnlyParser() )->addConfobulator(
new AmPmParser() )->accepts(
$time )
);
}
Heres the results from $times (second array)
Original dump array
0 => string '9' (length=1)
1 => string '0915' (length=4)
2 => string '9.00' (length=4)
3 => string '09:00' (length=5)
4 => string ' 09 ' (length=4)
5 => string ' 9 90 ' (length=6) // ambiguous, fail
6 => string '09: 001' (length=7) // too long, fail
7 => string '45:09' (length=5) // out of bounds fail
8 => string '9am:06' (length=6)
9 => string '-9-09' (length=5)
Results
string '09:00' (length=5)
string '09:15' (length=5)
string '09:00' (length=5)
string '09:00' (length=5)
string '09:00' (length=5)
boolean false
boolean false
boolean false
string '09:06' (length=5)
string '09:09' (length=5)
Like he says “You can then just chain them together to add more functionality, or tolerance if you will, to your application.”
If one object cannot handle the problem, it passes the ball to the next one, and so on. (what pattern is that?)
So you could have a range of time parsers, exactly what they would be rather leaves me wondering at the moment, but I am sure there are more.
The question of formatting as I said can be done in a number of ways, based on using the native strtotime().
Thanks for the time and discussion on this thread, and hoping it helps someone else to make their input fields just a teeny bit nicer to use.
The traditional way to deal with this problem of picking times is to give the user a number of pick boxes, which are OK if you were prompting a visitor to add one or two events a year, but for an adminner, adding maybe one or two events per day (an maybe adding dates and times in other applications too) then this routine of "leave the keyboard, get the mouse, pick on hours, scroll down to 21:00 from a list, go back to keyboard " starts to become tiresome.