Calculate text diffs in PHP
What sort of diffs? File diffs? There is array_diff() which acts on arrays. Then there is also xdiff, which "enables you to create and apply patch files containing differences between different revisions of files.". The latter acts on files or strings.
Edit: I should add xdiff doesn't appear to be out in a release yet. You have to build from source to use it.
PHP/JS Text Diff
Ok so it has been a while.
I actually decided to look around at what other people use and stumbled upon what Yii ( http://www.yiiframework.com ) uses.
They actually use the PEAR module for their text_diff
and they use it in its new form on the horde channel. It seems that text_diff
is now a horde project but you can just as easily integrate a version of it into your application and that is what Yii does by default (it comes pre-bundled with a version of it).
So I searched around a bit to find out how they used it and how to get into it and I came across:
public function actionDiff()
{
Yii::import('gii.components.TextDiff');
$model=$this->prepare();
if(isset($_GET['id']) && isset($model->files[$_GET['id']]))
{
$file=$model->files[$_GET['id']];
if(!in_array($file->type,array('php', 'txt','js','css')))
$diff=false;
elseif($file->operation===CCodeFile::OP_OVERWRITE)
$diff=TextDiff::compare(file_get_contents($file->path), $file->content);
else
$diff='';
$this->renderPartial('/common/diff',array(
'file'=>$file,
'diff'=>$diff,
));
}
else
throw new CHttpException(404,'Unable to find the code you requested.');
}
In CCodeGenerator
for their Gii module ( http://www.yiiframework.com/doc/api/1.1/CCodeGenerator/ ). The important part is where they actually hook into the PEAR module:
$diff=TextDiff::compare(file_get_contents($file->path), $file->content);
By reading in the contents of two files which produces a diffed
output.
Originally I did not want to use PEAR because of the bloat but this module is quite slim for a fully featured text_diff
so I have decided to go with this. Not only that but, at the moment, it is the only text_diff
module that has truly worked for me so I am keeping with the best, even if the best is quite memory hungry.
PHP text diff script
You might try using the PEAR Text_Diff it provides a text-based diff engine and renders for multiple diff output formats.
How to calculate the difference between two dates using PHP?
Use this for legacy code (PHP < 5.3). For up to date solution see jurka's answer below
You can use strtotime() to convert two dates to unix time and then calculate the number of seconds between them. From this it's rather easy to calculate different time periods.
$date1 = "2007-03-24";
$date2 = "2009-06-26";
$diff = abs(strtotime($date2) - strtotime($date1));
$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
printf("%d years, %d months, %d days\n", $years, $months, $days);
Edit: Obviously the preferred way of doing this is like described by jurka below. My code is generally only recommended if you don't have PHP 5.3 or better.
Several people in the comments have pointed out that the code above is only an approximation. I still believe that for most purposes that's fine, since the usage of a range is more to provide a sense of how much time has passed or remains rather than to provide precision - if you want to do that, just output the date.
Despite all that, I've decided to address the complaints. If you truly need an exact range but haven't got access to PHP 5.3, use the code below (it should work in PHP 4 as well). This is a direct port of the code that PHP uses internally to calculate ranges, with the exception that it doesn't take daylight savings time into account. That means that it's off by an hour at most, but except for that it should be correct.
<?php
/**
* Calculate differences between two dates with precise semantics. Based on PHPs DateTime::diff()
* implementation by Derick Rethans. Ported to PHP by Emil H, 2011-05-02. No rights reserved.
*
* See here for original code:
* http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/tm2unixtime.c?revision=302890&view=markup
* http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/interval.c?revision=298973&view=markup
*/
function _date_range_limit($start, $end, $adj, $a, $b, $result)
{
if ($result[$a] < $start) {
$result[$b] -= intval(($start - $result[$a] - 1) / $adj) + 1;
$result[$a] += $adj * intval(($start - $result[$a] - 1) / $adj + 1);
}
if ($result[$a] >= $end) {
$result[$b] += intval($result[$a] / $adj);
$result[$a] -= $adj * intval($result[$a] / $adj);
}
return $result;
}
function _date_range_limit_days($base, $result)
{
$days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
_date_range_limit(1, 13, 12, "m", "y", &$base);
$year = $base["y"];
$month = $base["m"];
if (!$result["invert"]) {
while ($result["d"] < 0) {
$month--;
if ($month < 1) {
$month += 12;
$year--;
}
$leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
$days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];
$result["d"] += $days;
$result["m"]--;
}
} else {
while ($result["d"] < 0) {
$leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
$days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];
$result["d"] += $days;
$result["m"]--;
$month++;
if ($month > 12) {
$month -= 12;
$year++;
}
}
}
return $result;
}
function _date_normalize($base, $result)
{
$result = _date_range_limit(0, 60, 60, "s", "i", $result);
$result = _date_range_limit(0, 60, 60, "i", "h", $result);
$result = _date_range_limit(0, 24, 24, "h", "d", $result);
$result = _date_range_limit(0, 12, 12, "m", "y", $result);
$result = _date_range_limit_days(&$base, &$result);
$result = _date_range_limit(0, 12, 12, "m", "y", $result);
return $result;
}
/**
* Accepts two unix timestamps.
*/
function _date_diff($one, $two)
{
$invert = false;
if ($one > $two) {
list($one, $two) = array($two, $one);
$invert = true;
}
$key = array("y", "m", "d", "h", "i", "s");
$a = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $one))));
$b = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $two))));
$result = array();
$result["y"] = $b["y"] - $a["y"];
$result["m"] = $b["m"] - $a["m"];
$result["d"] = $b["d"] - $a["d"];
$result["h"] = $b["h"] - $a["h"];
$result["i"] = $b["i"] - $a["i"];
$result["s"] = $b["s"] - $a["s"];
$result["invert"] = $invert ? 1 : 0;
$result["days"] = intval(abs(($one - $two)/86400));
if ($invert) {
_date_normalize(&$a, &$result);
} else {
_date_normalize(&$b, &$result);
}
return $result;
}
$date = "1986-11-10 19:37:22";
print_r(_date_diff(strtotime($date), time()));
print_r(_date_diff(time(), strtotime($date)));
Highlight the difference between two strings in PHP
You were able to use the PHP Horde_Text_Diff package.
However this package is no longer available.
Compare 2 strings and display difference (php or javascript)
This answer to a related question seems promising for javascript. google-diff-match-patch
It provides an API which will take care of all the complex and well known algorithms. However you'll have to do some work with the presentation.
PHP is more versatile there is a lot of diff tools out there.
Look this other related question Calculate text diffs in PHP.
Count the number of differences between two string in php?
Maybe this helps. I forked the comment from Anant.
$first_str = "abcdez";
$second_str= "abhdx";
$first_str_array = str_split($first_str);
$second_str_array = str_split($second_str);
$first_count = count($first_str_array);
$second_count = count($second_str_array);
if (($first_count - $second_count) > 0) {
$count = $first_count - $second_count;
unset($first_str_array[$first_count-$count]);
} else if (($second_count - $first_count) > 0){
$count = $second_count - $first_count;
unset($second_str_array[$second_count-$count]);
}
$final_difference = array_diff($first_str_array,$second_str_array);
Calculate Absolute Differences between Dates in PHP
Here's a function that does 99% of what you want (it doesn't implement rounding when length != 'l'
, and it also doesn't remove the s
from e.g. 1 years
). 0 values are not output, although you could add a parameter to control that.
function friendlyDtmDiff($date1, $date2, $length = '', $format = '') {
// Create DateTime for diff()
$dt1 = new \DateTime($date1);
$dt2 = new \DateTime($date2);
// Create intervals
if ($dt1 < $dt2) {
$sign = '';
$interval = $dt1->diff($dt2);
}
else {
$sign = '-';
$interval = $dt2->diff($dt1);
}
// Output format (minimum 2 digits for upper case formats)
$of = ($format < 'a') ? '%02d' : '%d';
// generate output using an array of terms to be imploded
$output = array();
// create time components
switch ($format) {
case 'Y':
case 'y':
$years = $interval->y;
if ($years) $output[] = sprintf("$of years", $years);
if ($length != 'l') break;
$interval->y = 0;
case 'M':
case 'm':
$months = $interval->y * 12 + $interval->m;
if ($months) $output[] = sprintf("$of months", $months);
if ($length != 'l') break;
$interval->m = $interval->y = 0;
case 'D':
case 'd':
$days = ($interval->y * 12 + $interval->m) * 30 + $interval->d;
if ($days) $output[] = sprintf("$of days", $days);
if ($length != 'l') break;
$interval->d = $interval->m = $interval->y = 0;
case 'H':
case 'h':
$hours = (($interval->y * 12 + $interval->m) * 30 + $interval->d) * 24 + $interval->h;
if ($hours) $output[] = sprintf("$of hours", $hours);
if ($length != 'l') break;
$interval->h = $interval->d = $interval->m = $interval->y = 0;
case 'I':
case 'i':
$minutes = ((($interval->y * 12 + $interval->m) * 30 + $interval->d) * 24 + $interval->h) * 60 + $interval->i;
if ($minutes) $output[] = sprintf("$of minutes", $minutes);
if ($length != 'l') break;
$interval->i = $interval->h = $interval->d = $interval->m = $interval->y = 0;
case 'S':
case 's':
$seconds = (((($interval->y * 12 + $interval->m) * 30 + $interval->d) * 24 + $interval->h) * 60 + $interval->i) * 60 + $interval->s;
if ($seconds) $output[] = sprintf("$of seconds", $seconds);
break;
default:
return 'Invalid format';
break;
}
// put the output string together
$last = array_pop($output);
return $sign . (count($output) ? implode(', ', $output) . ' and ' : '') . $last;
}
Example usage:
echo friendlyDtmDiff('2020-02-28 00:00:00', '2020-03-01 12:00:56', '', 'h') . PHP_EOL;
echo friendlyDtmDiff('2020-02-28 00:00:00', '2020-03-01 12:00:56', 'l', 'h') . PHP_EOL;
echo friendlyDtmDiff('2020-02-28 00:00:00', '2020-03-01 12:08:56', 'l', 'h') . PHP_EOL;
echo friendlyDtmDiff('2018-12-28 00:00:00', '2020-04-11 04:08:56', 'l', 'y') . PHP_EOL;
echo friendlyDtmDiff('2018-12-28 00:00:00', '2020-04-11 04:08:56', 'l', 'm') . PHP_EOL;
echo friendlyDtmDiff('2018-12-28 00:00:00', '2020-04-11 04:08:56', 'l', 'd') . PHP_EOL;
echo friendlyDtmDiff('2018-12-28 00:00:00', '2020-04-11 04:08:56', 'l', 'h') . PHP_EOL;
echo friendlyDtmDiff('2018-12-28 00:00:00', '2020-04-11 04:08:56', 'l', 'i') . PHP_EOL;
echo friendlyDtmDiff('2018-12-28 00:00:00', '2020-04-11 04:08:56', 'l', 's') . PHP_EOL;
Output:
60 hours
60 hours and 56 seconds
60 hours, 8 minutes and 56 seconds
1 years, 3 months, 14 days, 4 hours, 8 minutes and 56 seconds
15 months, 14 days, 4 hours, 8 minutes and 56 seconds
464 days, 4 hours, 8 minutes and 56 seconds
11140 hours, 8 minutes and 56 seconds
668408 minutes and 56 seconds
40104536 seconds
Demo on 3v4l.org
How to calculate difference of two string dates in days using PHP?
Try this, use date_create
$dnow = "2016-12-1";
$dafter = "2016-12-11";
$date1=date_create($dnow);
$date2=date_create($dafter);
$diff=date_diff($date1,$date2);
print_r($diff);
DEMO
Related Topics
Programmatically Access Currency Exchange Rates
PHP Fatal Error: Call to Undefined Function MySQLi_Stmt_Get_Result()
Submitting JSON Data via Jquery Ajax.Post to PHP
Custom Order Status Background Button Color in Woocommerce 3.3 Admin Order List
Php: Variable Not Working Inside of Function
Swift Httppost Data Not Inserting to MySQL Database
Sorting Multidim Array: Prioritize If Column Contains Substring, Then Order by a Second Column
How to Get Int Instead String from Form
Get Numbers from String with PHP
How to Send Email with Attachment Using PHP
PHP Upload, Extract and Progressbar
Strange Behaviour with Numbers That Have a Leading Zero
How to Send Email from Localhost Using PHP on Linux