php - uniformize date strings with different formats - php

I have an array with many different formats of dates. All strings.
I want to uniformize this into an array with dates(). Something like this:
function uniformize($str){
$date = strtotime($str);
return $date;
}
$arr = array(
'07/29/1975',
'20/01/1981',
'1983-05-24',
'10 /8 /1995'
);
print_r( array_map('uniformize', $arr) );
But this only works with one format:
Array (
[0] =>
[1] =>
[2] => 454215600
[3] =>
)
Is there any way I can do it for all formats?

You can use this function for that. Fiddle here
Notice it's supposed to have always the days before than the months. Otherwise it's impossible to know whether first part of the date is a day or a month (unless the day is more than 12.. and can't cover all the cases).
function date2time($date)
{
$date = str_replace(' ','',$date);
if(strpos($date,'-')!==false)
$date_array = explode('-',$date);
if(strpos($date,'/')!==false)
$date_array = explode('/',$date);
//add more delimiters if needed
$day = $month = $year = '';
foreach($date_array as $date_elem)
{
if(strlen($date_elem) < 3)
{
if(empty($day))
$day = $date_elem;
else
$month = $date_elem;
}else
$year = $date_elem;
}
$time = mktime(0,0,0,$month,$day,$year);
return $time;
}
$arr = array(
'07/29/1975',
'20/01/1981',
'1983-05-24',
'10 /8 /1995'
);
print_r( array_map('date2time', $arr) );

Unfortunately, I think you have to detect yourself the format and then convert it into the format you wish...
The real problem is about months and days...
some use 31-12-2014, other countries use 12-31-2014...
so you HAVE to define which is the month and the day in a string like 05-06-2015...
EDIT :
You have many regex to do...
I'm using this for 2015-12-31 format :
if(preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $yourDate, $split)) && (checkdate($split[2],$split[3],$split[1]))) {
// do stuff where $split[1] is years, split[2] is month, and split[3] is day
}
Then you may adapt it to every formats you encounter changing order...
checkdate checks if it is a valide date (2015-52-38 is not a valid date)
You may also find some on google with "date pattern regex" for instance...

The first two strings use / as component separator. The function strtotime consider them to be formatted according to the American format: month/day/year. Because 24 and 20 are invalid month numbers they cannot be parsed correctly.
The last string ('10 /8 /1995') looks like a short date format but the spaces inside the components also render it invalid.
As it is explained in a note in the documentation of function strtotime():
Note:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed.
What can you do
If you know the order of components in your dates you can use str_replace() to always use / for m/d/y (the American format) and - for d-m-y (the European format). Also, you should strip the spaces.
Another option is to write your own date parser to identify the date components then use mktime() or DateTime::setDate() to get the date. However, if the date have both the day and the month in 1..12, the format cannot be detected and it have to be assumed (from the separator).

Related

Process Array and change date format

I asked a question earlier but realised I was asking the wrong thing. I have an array which takes the following format
Array
(
[0] => Array
(
[ID] => 10000
[Date] => 21/11/2013
[Total] => 10
)
...
)
So it has an ID, Date and Total. One issue is, I do not know what format the Date column might be, but whatever format it is I need to convert it into the format dmy.
So I am looping my array, I know that the key will always be Date.
foreach($this->csvData as $item) {
foreach($item as $key => $value) {
if($key === 'Date') {
$item[$key][$value] = date("dmy", strtotime($value));
}
}
}
I am experiencing a couple of issues with the above. Firstly, after the looping, if I output $this->csvData, the date values have not been converted to the new values. I know I am in the right place because if I do this inside the if
print_r(date("dmy", strtotime($value));
I can see the altered dates. I dont think I am reassigning them correctly though?
The other thing I am attempting to do is this. If the date is completely wrong, say some random thing like 23455, then I want to remove the whole element from the array.
Is this possible? I know about validating dates, but it always seems to be validating against one particular format, whereas I do not know what the format will be.
Thanks
Your problem lay in dd/mm/yyyy format.
From strtotime documentation:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at
the separator between the various components: if the separator is a
slash (/), then the American m/d/y is assumed; whereas if the
separator is a dash (-) or a dot (.), then the European d-m-y format
is assumed. If, however, the year is given in a two digit format and
the separator is a dash (-), the date string is parsed as y-m-d.
To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD)
dates or DateTime::createFromFormat() when possible.
So "21/11/2013" fail as there is no month 21...
Use - as "21-11-2013"
If you don't know the format you can check the return value of strtotime before:
$arr = [["id" => 100, "data" => "21-11-2013"]];
foreach($arr as $k => &$e) {
$val = strtotime($e["data"]) ? strtotime($e["data"]) : strtotime(str_replace("/", "-", $e["data"]));
$e["data"] = date("m/d/y", $val);
if (!$val) unset($arr[$k]); // if non valid date remove from array
}
Live example: 3v4l

why strtotime isn't working on php

I'm trying to compare between two date but unfortunately this isn't working by converting this into UNIX format with strtotime. I'm trying to compare a date to another date.
However this format is working:
if(strtotime("22-04-17") < strtotime("25-05-17")){
echo 'Date One is smaller than date two';
}
But Many times it's failing. I've seen a lot of examples on the web but I can't figure out anything good!
if(strtotime("22-04-17") < strtotime("04-05-17")){ //passing still the
// bigger on but not working
echo 'Date One is smaller than date two';
}
From the manual (make special note of the part I've put in bold):
"Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed. If, however, the year is given in a two digit format and the separator is a dash (-, the date string is parsed as y-m-d."
So here's what you're doing, with the dates PHP is interpreting your strings as in comments:
// Is 17 April 2022 earlier than 17 May 2025? Yes.
if(strtotime("22-04-17") < strtotime("25-05-17")){
echo 'Date One is smaller than date two';
}
// Is 17 April 2022 earlier than 17 May 2004? No.
if(strtotime("22-04-17") < strtotime("04-05-17")){ //passing still the
// bigger on but not working
echo 'Date One is smaller than date two';
}
I hope this makes the problem you're having clear.
As it also says in the manual, use DateTime::createFromFormat/date_create_from_format if you want to avoid ambiguity:
$date = date_create_from_format('d-m-y', '04-05-17'); // 4 May 2017
your comparsion is not working because strtotime("22-04-17") actually results to timestamp for this date: 17th April 2022;
Do the following and you will see what I mean. the following code will output '2022-May-17`
$date = "22-05-17";
echo date ("Y-M-d ",strtotime($date))."<br>";
Try this
$date1 = date('d-m-y',strtotime("22-04-17"));
$date2 = date('d-m-y',strtotime("04-05-17"));;
if((int)strtotime($date1) < (int)strtotime($date2)){ //passing still the
echo 'Date One is smaller than date two';
}
Your year format 17 causing the problem in strtotime function
I know this isn't what you're looking for but have you tried doing this to showing if date greater / smaller?
// Dates
$Date1 = strtotime("22-04-17 GMT");
$Date2 = strtotime("04-05-17 GMT");
// Diff between dates
$Diff = (int)floor(($Date1 - $Date2) / (60*60*24));
if ($Diff < 0) {
echo "The Diff is negative";
}
Then the other way is like this answer: LINK
$date1 = strtotime("22-04-17 GMT");
$date2 = strtotime("04-05-17 GMT");
if((int)strtotime($date1) < (int)strtotime($date2)){ //passing still the
echo 'Date One is smaller than date two';
}
I wrote a function that takes your datestring and properly return timestmp. Please note that I followed PHP's convention of treating 2 digit years, i.e. 00-69 are mapped to 2000-2069 and 70-99 to 1970-1999
/* functon takes dateString of format dd-dd-yy and return proper timestamp */
function getTimestamp($dateString)
{
$res = preg_match('/^([0-9]{2})\-([0-9]{2})-([0-9]{2})/', $dateString, $matches);
if(!$res)
return 0;
//00-69 are mapped to 2000-2069 and 70-99 to 1970-1999
if($matches[3]>=70 && $matches[3]<=99 )
$year = "19".$matches[3];
else
$year = "20".$matches[3];
$formatted_dat_string = $year."-".$matches[2]."-".$matches[1];
return strtotime($formatted_dat_string);
}
getTimestamp("22-04-99");
So you can now use this function instead of strtotime for comparison.
Finally, I got the solution. The strtotime() isn't any good to handle this case. You should go for dateTime object instead.
//First you need to pass the original format then you will need to pass new
//Format to get this working properly. Hope this will help you guy's
$myDateTimestart = DateTime::createFromFormat('d-m-Y', $dateString);
$startDate = $myDateTimestart->format('m-d-Y');
//with Simply that you can format your date properly
I just Messed my times with this thing it was really bad

Check if date is in the next 3 days PHP

I have a date stored in my DB (due_date)
I am wanting to write a script that checks if the due_date is in the next 3 days
From checking online (google) i have found some code but it doesnt seem to work, see below
if (time() - filemtime($due_date) >= 3 * 86400)
{
echo" Invoice $id is due in the next 3 days<br />";
}
else
{
echo" Invoice $id not due in the next 3 days </br>";
}
$due_date contains a date in the format 01/01/2015
Please can someone help with this? P.s I am a newbie!
Thanks
Use strtotime() to convert the date string to a unix timestamp, and edit your if statement accordingly:
$seconds_to_expire = strtotime($due_date) - time();
if ($seconds_to_expire < 3*86400) {
...
Note that dates in the m/d/y or d/m/y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed (see this). You may want to convert your date to a Y-m-d format instead:
$due_date_ymd = date('Y-m-d', strtotime(str_replace('/', '-', $due_date));
$seconds_to_expire = strtotime($due_date_ymd) - time();
if ($seconds_to_expire < 3*86400) {
...
Change
filemtime($due_date)
to
strtotime(str_replace('/', '-', $due_date))
you have to change / to - if the day comes first, otherwise php will assume that first is month!
if (strtotime($due_date)+60*60*24*3 =< time()+60*60*24*3) {
echo "Is due in the next 3 days"
} else {
echo "Is not due in the next 3 days"
}
You could translate the DB date value (which is in the format 'yyyy-mm-dd') to a DateTime object and then compare:
$d = DateTime::createFromFormat('Y-m-d', $due_date);
$d->modify('-3 days'); // subtract 3 days from due date
if ($d < new DateTime()) {
echo 'date is due within 3 days';
}
Notes:
new DateTime() will give you the current date.
I assume that $due_date is a string in the format 'yyyy-mm-dd', as you should get if it is a Date column in the database.
Since you commented that $due_date is "A date in the format 01/01/2015", you can easily ajust the code: change the format specifier in the createFromFormat function from 'Y-m-d' into 'd/m/Y'.

PHP date conversion from user input

I am trying to convert a user inputted date so I can use it to search in MySQL. This is my code -
<form name="date_form" action="" method="POST"">
<input type="text" name="start_date" value="<?php echo date('d/m/Y');?>"/>
<input type="submit" name="submit_start" value="Submit" />
<?php
if(isset($_POST["submit_start"]))
{
$date_1 = mysqli_real_escape_string($dbc, trim($_POST['start_date']));//checking that I am getting something from the input
$newDate = date("Y-m-d", strtotime($_POST['start_date']));//converting date from the input to SQL format
echo '<br>date 1 = '.$date_1.'<br>';
echo 'date 2 = '.$newDate.'<br>';
$start_date = '2013-12-13';
echo 'date 3 = '.$start_date.'<br>';//Just to compare formats
$report = create_user_report($dbc, $start_date);
}
and this is the output
date 1 = 14/12/2013
date 2 = 1970-01-01
date 3 = 2013-12-13
2013-12-13
I was expecting date 2 to be 2013-12-13, the format appears to be ok but the value isnt. I have played with many different ways of getting the value, all have been wrong!
So I have two questions please
1. How can I get the correct value in the code above?
2. I want to use this value to search a MySQL table and return a count of dates that match it. Once the above is working, is that the best way to do it - or is there a better way?
Many thanks
From the strtotime manual:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between
the various components: if the separator is a slash (/), then the American m/d/y is
assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y
format is assumed.
So:
$newDate = date("Y-m-d", strtotime($_POST['start_date']))
is asking for the 12th day of the 14th month.
Try replacing the / with -
$date = str_replace ( '/' , '-' , $_POST['start_date'])
The problem is caused because when confronted with /, strtotime assumes the time to be in the American format of m/d/Y (instead of d/m/Y). Read the manual on strtotime (especially the Notes) for more information.
And because 14/12/2013 is not valid in the American format, you'll get the default time (aka UNIX timestamp 0).
Since this is user input and you cannot be sure if he really means to use the American format or is misusing it, you could do a check before the conversion like this
//check if input is a date in the American format
if (preg_match("#^(\d+)/(\d+)/(\d+)$#", $_POST['start_date'], $matches)) {
if ($matches[1] > $matches[2]) {
$day = $matches[1];
$month = $matches[2];
} else {
$day = $matches[2];
$month = $matches[1];
}
$start_date = $month.'/'.$day.'/'.$matches[3];
}
However if a user inputs e.g. 04/05/2013 this will be interpreted in the American format, although the user could have meant it in d/m/Y.
"Explode" seems to be commonly used in situations like this.
$mydate = $_POST["submit_start"];
list ($y, $m, $d) = explode('/', $mydate);
$mydate = sprintf("%02d-%02d-%04d", $m, $d, $y);
strtotime requires the English date format as input - HERE.
strtotime() PHP Manual
Take a look over there, it reports
The function expects to be given a string containing an English date format
And that's why your function doesn't work as you expect. In fact, d/m/Y is NOT an american date format. Here, take a look, I made you some examples to let you see how to make it work: Click here - eval.in
<?php
echo strtotime(date('m/d/Y'));
echo strtotime(date('d/m/Y'));
echo strtotime(date('d-m-Y'));
echo strtotime(date('d/m/Y'));
echo strtotime(date('Y-m-d'));
echo strtotime(date('Y/m/d'));
?>
Produces
1386979200
FALSE
1386979200
FALSE
1386979200
1386979200
Since you'll never know what kind of date format (or if it's actually a date at all) an user may input, I suggest you to use a date picker plugin on your input, that'll be very useful, or you may want to use a regular expression that other user suggested.
For the mysql part you can easly compare two dates with the MySQL Date Function
Since I don't know your query I'll just provide you the part you need for the comparsion in the query:
... WHERE DATE(some_date) = DATE(some_other_date) ...
Where some_date and some_other_date are two valid date formats as written above.

PHP - checking if two dates match but ignoring the year

I have an array which will output a date. This date is outputted in the mm/dd/yyyy format. I have no control over how this outputted so I cant change this.
Array
(
[date] => 04/06/1989
)
I want to use php to check if this date matches the current date (today), but ignoring the year. So in the above example I just want to check if today is the 6th April. I am just struggling to find anything which documents how to ignore the years.
if( substr( $date, 0, 5 ) == date( 'm/d' ) ) { ...
Works only if it's certain that the month and date are both two characters long.
Came in a little late, but here’s one that doesn’t care what format the other date is in (e.g. “Sep 26, 1989”). It could come in handy should the format change.
if (date('m/d') === date('m/d', strtotime($date))) {
echo 'same as today';
} else {
echo 'not same as today';
}
this will retrieve the date in the same format:
$today = date('m/d');
Use this:
$my_date = YOUR_ARRAY[date];
$my_date_string = explode('/', $my_date);
$curr_date = date('m,d,o');
$curr_date_string = explode(',', $date);
if (($my_date_string[0] == $curr_date_string[0]) && ($my_date_string[1] == $curr_date_string[1]))
{
DO IT
}
This way, you convert the dates into strings (day, month, year) which are saved in an array. Then you can easily compare the first two elements of each array which contains the day and month.
You can use for compare duple conversion if you have a date.
$currentDate = strtotime(date('m/d',time())); --> returns current date without care for year.
//$someDateTime - variable pointing to some date some years ago, like birthday.
$someDateTimeUNIX = strtotime($someDateTime) --> converts to unix time format.
now we convert this timeunix to a date with only showing the day and month:
$dateConversionWithoutYear = date('m/d',$someDateTimeUNIX );
$dateWithoutRegardForYear = strtotime($dateConversionWithoutYear); -->voila!, we can now compare with current year values.
for example: $dateWithoutRegardForYear == $currentDate , direct comparison
You can convert the other date into its timestamp equivalent, and then use date() formatting to compare. Might be a better way to do this, but this will work as long as the original date is formatted sanely.
$today = date('m/Y', time());
$other_date = date('m/Y', strtotime('04/06/1989'));
if($today == $other_date) {
//date matched
}
hi you can just compare the dates like this
if(date('m/d',strtotime($array['date']])) == date('m/d',strtotime(date('Y-m-d H:i:s',time()))) )

Categories