It seems that you have a more serious problem than just date formatting: they are standardized or standardized in a single input type / format.
As this does not fit the scope of the topic, if I have assumed correctly, the solution presented by Zuul, although correct from a programmatic point of view, is not enough because it takes into account a single date format.
So, I offer the function below, created by a forum friend introduced here in the other topic community:
/**
* Altera uma data para outro formato
*
* @param string $date String contendo a data a ser formatada
* @param string $outputFormat Formato de saida
* @throws Exception Quando não puder converter a data
* @return string Data formatada
* @author Hugo Ferreira da Silva
*/
function parseDate($date, $outputFormat = 'd/m/Y'){
$formats = array(
'd/m/Y',
'd/m/Y H',
'd/m/Y H:i',
'd/m/Y H:i:s',
'Y-m-d',
'Y-m-d H',
'Y-m-d H:i',
'Y-m-d H:i:s',
);
foreach($formats as $format){
$dateObj = DateTime::createFromFormat($format, $date);
if($dateObj !== false){
break;
}
}
if($dateObj === false){
throw new Exception('Invalid date:' . $date);
}
return $dateObj->format($outputFormat);
}
To test:
$testDates = array(
'2012-10-30 00:00:00',
'06/01/1986 14',
'06/12/1983 14:30:10',
'1984-01-06 14:30:10',
);
foreach($testDates as $date){
var_dump( parseDate($date, 'Y-m-d') );
//var_dump( DateTime::createFromFormat('d/m/Y', $date) instanceof DateTime );
}
Output:
string '2012-10-30' (length=10)
string '1986-01-06' (length=10)
string '1983-12-06' (length=10)
string '1984-01-06' (length=10)
Just to illustrate why Zuul's solution is not enough, try experimenting with this same array of random dates to create a DateTime object without changing the format:
foreach($testDates as $date){
var_dump( DateTime::createFromFormat('d/m/Y', $date) instanceof DateTime );
}
All four iterations result in FALSE because none of them are in the d / m / Y format whereas the function presented here takes into account the eight major date / time formats. >
As explained in the comments in this answer the function presented here causes 11/12/2014 to return 2014-12-11 which although validly programmatically does not compute with the required logic.
This is because the function primarily takes dates into the Brazilian DAY / MONTH / YEAR format and as foreach
is interrupted when a format is successfully created by a DateTime object it results in a false positive.
The solution is quite simple, just reorder the array $ formats in the way that suits you best.
For example:
$formats = array(
'Y-m-d',
'Y-m-d H',
'Y-m-d H:i',
'Y-m-d H:i:s',
'd/m/Y',
'd/m/Y H',
'd/m/Y H:i',
'd/m/Y H:i:s',
);
You have 11/12/2014 returned 2014-12-11 and 10/30/2014 return 2014 -10-30 .
One more consideration:
In the same way that you can and should reorder the array of formats as best you can, you can also include new formats specific to your needs.
As the first of your dates is in a format valid for a date but not considered in the available formats (m / d / Y), simply add it to the array:
$formats = array(
'm/d/Y', // <---
'Y-m-d',
'Y-m-d H',
'Y-m-d H:i',
'Y-m-d H:i:s',
'd/m/Y',
'd/m/Y H',
'd/m/Y H:i',
'd/m/Y H:i:s',
);
But keep in mind that both this solution and Zuul's proposal will fail according to the logic you expect because your dates are not normalized.
As far as I know there is no way to automatically detect if a given component of a date is a day, a month, or a year.
Placing the new m / d / Y format at the beginning of $ formats will return what you expect for the first date. But for the second it would return 2016-06-10 , which I imagine to be a DateTime issue itself because there is no month 30.