Skip to content

Commit

Permalink
Merge pull request #6 from defrag/precise-diff
Browse files Browse the repository at this point in the history
Precise diffs
  • Loading branch information
norberttech committed Apr 29, 2014
2 parents 7438be8 + f62ed58 commit 08b9d1b
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 2 deletions.
18 changes: 18 additions & 0 deletions spec/Coduo/PHPHumanizer/DateTimeSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,22 @@ function it_humanize_difference_between_dates_for_pl_locale()
$this->difference(new \DateTime($example[0]), new \DateTime($example[1]), 'pl')->shouldReturn($example[2]);
}
}

function it_humanizes_precise_difference_between_dates()
{
$examples = array(
array("2014-04-26 13:00:00", "2014-04-26 12:58:15", '1 minute, 45 seconds ago'),
array("2014-04-26 13:00:00", "2014-04-26 11:20:00", '1 hour, 40 minutes ago'),
array("2014-04-26 13:00:00", "2014-04-27 13:15:00", '1 day, 15 minutes from now'),
array("2014-04-26 13:00:00", "2014-05-03 15:00:00", '1 week, 2 hours from now'),
array("2014-04-26 13:00:00", "2015-04-28 17:00:00", '1 year, 1 week, 4 days, 4 hours from now'),
array("2014-04-26 13:00:00", "2014-04-28 23:00:00", '2 days, 10 hours from now'),
array("2014-04-26 13:00:00", "2014-04-25 11:20:00", '1 day, 1 hour, 40 minutes ago'),
);

foreach ($examples as $example) {
$this->preciseDifference(new \DateTime($example[0]), new \DateTime($example[1]))->shouldReturn($example[2]);
}
}

}
8 changes: 8 additions & 0 deletions src/Coduo/PHPHumanizer/DateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Coduo\PHPHumanizer;

use Coduo\PHPHumanizer\DateTime\Difference;
use Coduo\PHPHumanizer\DateTime\PreciseDifference;
use Coduo\PHPHumanizer\DateTime\Formatter;
use Coduo\PHPHumanizer\DateTime\PreciseFormatter;
use Coduo\PHPHumanizer\Translator\Builder;

class DateTime
Expand All @@ -13,4 +15,10 @@ public static function difference(\DateTime $fromDate, \DateTime $toDate, $local
$formatter = new Formatter(Builder::build($locale));
return $formatter->formatDifference(new Difference($fromDate, $toDate), $locale);
}

public static function preciseDifference(\DateTime $fromDate, \DateTime $toDate, $locale = 'en')
{
$formatter = new PreciseFormatter(Builder::build($locale));
return $formatter->formatDifference(new PreciseDifference($fromDate, $toDate), $locale);
}
}
1 change: 0 additions & 1 deletion src/Coduo/PHPHumanizer/DateTime/Difference.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ private function calculate()
}
}


$this->quantity = ($absoluteMilliSecondsDiff == 0)
? $absoluteMilliSecondsDiff
: (int) round($absoluteMilliSecondsDiff / $this->unit->getMilliseconds());
Expand Down
53 changes: 53 additions & 0 deletions src/Coduo/PHPHumanizer/DateTime/Difference/CompoundResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Coduo\PHPHumanizer\DateTime\Difference;

use Coduo\PHPHumanizer\DateTime\Unit;

class CompoundResult
{
/**
* @var \Coduo\PHPHumanizer\DateTime\Unit
*/
private $unit;
private $quantity;

public function __construct(Unit $unit, $quantity)
{
$this->unit = $unit;
$this->quantity = $quantity;
}

/**
* @param mixed $quantity
*/
public function setQuantity($quantity)
{
$this->quantity = $quantity;
}

/**
* @return mixed
*/
public function getQuantity()
{
return $this->quantity;
}

/**
* @param \Coduo\PHPHumanizer\DateTime\Unit $unit
*/
public function setUnit($unit)
{
$this->unit = $unit;
}

/**
* @return \Coduo\PHPHumanizer\DateTime\Unit
*/
public function getUnit()
{
return $this->unit;
}

}
91 changes: 91 additions & 0 deletions src/Coduo/PHPHumanizer/DateTime/PreciseDifference.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Coduo\PHPHumanizer\DateTime;

use Coduo\PHPHumanizer\DateTime\Unit\Day;
use Coduo\PHPHumanizer\DateTime\Unit\Hour;
use Coduo\PHPHumanizer\DateTime\Unit\JustNow;
use Coduo\PHPHumanizer\DateTime\Unit\Minute;
use Coduo\PHPHumanizer\DateTime\Unit\Month;
use Coduo\PHPHumanizer\DateTime\Unit\Second;
use Coduo\PHPHumanizer\DateTime\Unit\Week;
use Coduo\PHPHumanizer\DateTime\Unit\Year;
use Coduo\PHPHumanizer\DateTime\Difference\CompoundResult;

class PreciseDifference
{
/**
* @var \DateTime
*/
private $fromDate;

/**
* @var \DateTime
*/
private $toDate;

/**
* @var \Coduo\PHPHumanizer\DateTime\Unit[]
*/
private $units;

/**
* @var \Coduo\PHPHumanizer\DateTime\Difference\CompoundResult[]
*/
private $compoundResults;

public function __construct(\DateTime $fromDate, \DateTime $toDate)
{
$this->fromDate = $fromDate;
$this->toDate = $toDate;
$this->calculate();
}

/**
* @return \Coduo\PHPHumanizer\DateTime\Difference\CompoundResult[]
*/
public function getCompoundResults()
{
return $this->compoundResults;
}

private function calculate()
{
/* @var $units \Coduo\PHPHumanizer\DateTime\Unit[] */
$units = array(
new Year(),
new Month(),
new Week(),
new Day(),
new Hour(),
new Minute(),
new Second(),
);

$absoluteMilliSecondsDiff = abs($this->toDate->getTimestamp() - $this->fromDate->getTimestamp()) * 1000;

foreach ($units as $unit) {
if ($absoluteMilliSecondsDiff >= $unit->getMilliseconds()) {
$this->units[] = $unit;
}
}

foreach ($this->units as $unit) {
$quantity = (int) floor($absoluteMilliSecondsDiff / $unit->getMilliseconds());

if ($quantity === 0) {
continue;
}

$this->compoundResults[] = new CompoundResult($unit, $quantity);
$absoluteMilliSecondsDiff -= ($quantity * $unit->getMilliseconds());
}

}

public function isPast()
{
$diff = $this->toDate->getTimestamp() - $this->fromDate->getTimestamp();
return ($diff > 0) ? false : true;
}
}
45 changes: 45 additions & 0 deletions src/Coduo/PHPHumanizer/DateTime/PreciseFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Coduo\PHPHumanizer\DateTime;

use Symfony\Component\Translation\TranslatorInterface;

class PreciseFormatter
{
/**
* @var \Symfony\Component\Translation\TranslatorInterface
*/
private $translator;

/**
* @param TranslatorInterface $translator
*/
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}

/**
* @param PreciseDifference $difference
* @param string $locale
* @return string
*/
public function formatDifference(PreciseDifference $difference, $locale = 'en')
{
$diff = array();

foreach ($difference->getCompoundResults() as $result) {

$diff[] = $this->translator->transChoice(
"compound." . $result->getUnit()->getName(),
$result->getQuantity(),
array('%count%' => $result->getQuantity()),
'difference',
$locale
);

}
$suffix = $difference->isPast() ? 'compound.ago' : 'compound.from_now';
return join(", ", $diff) . ' '. $this->translator->trans($suffix, array(), 'difference', $locale);
}
}
11 changes: 11 additions & 0 deletions src/Coduo/PHPHumanizer/Resources/translations/difference.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,14 @@ month:
year:
past: "{1} %count% year ago|[2,Inf] %count% years ago"
future: "{1} %count% year from now|[2,Inf] %count% years from now"

compound:
second: "{1} %count% second|[2,Inf] %count% seconds"
minute: "{1} %count% minute|[2,Inf] %count% minutes"
hour: "{1} %count% hour|[2,Inf] %count% hours"
day: "{1} %count% day|[2,Inf] %count% days"
week: "{1} %count% week|[2,Inf] %count% weeks"
month: "{1} %count% month|[2,Inf] %count% months"
year: "{1} %count% year|[2,Inf] %count% years"
ago: "ago"
from_now: "from now"
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ month:
future: "{1} za miesiąc|[2, 4] za %count% miesiące|[5,Inf] za %count% miesięcy"
year:
past: "{1} rok temu|[2, 4] %count% lata temu|[5,Inf] %count% lat temu"
future: "{1} za rok|[2, 4] za %count% lata|[5,Inf] za %count% lat"
future: "{1} za rok|[2, 4] za %count% lata|[5,Inf] za %count% lat"

0 comments on commit 08b9d1b

Please sign in to comment.