Skip to content

Commit

Permalink
Merge pull request #5 from norzechowicz/time
Browse files Browse the repository at this point in the history
[WIP] Introduce time difference humanizer
  • Loading branch information
defrag committed Apr 28, 2014
2 parents 6181797 + 3dbd614 commit 7438be8
Show file tree
Hide file tree
Showing 20 changed files with 669 additions and 1 deletion.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,37 @@ use Coduo\PHPHumanizer\Number;
echo Number::metricSuffix(1240000, 'pl'); // "1,24M"
```

## Date time

**Difference**

```php
use Coduo\PHPHumanizer\DateTime;

echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 13:00:00"); // just now
echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 13:00:05"); // 5 seconds from now
echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 12:59:00"); // 1 minute ago
echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 12:45:00"); // 15 minutes ago
echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 13:15:00"); // 15 minutes from now
echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 14:00:00"); // 1 hour from now
echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 15:00:00"); // 2 hours from now
echo DateTime::difference(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 12:00:00"); // 1 hour ago
echo DateTime::difference(new \DateTime("2014-04-26"), new \DateTime("2014-04-25"); // 1 day ago
echo DateTime::difference(new \DateTime("2014-04-26"), new \DateTime("2014-04-24"); // 2 days ago
echo DateTime::difference(new \DateTime("2014-04-26"), new \DateTime("2014-04-28"); // 2 days from now
echo DateTime::difference(new \DateTime("2014-04-01"), new \DateTime("2014-04-15"); // 2 weeks from now
echo DateTime::difference(new \DateTime("2014-04-15"), new \DateTime("2014-04-07"); // 1 week ago
echo DateTime::difference(new \DateTime("2014-01-01"), new \DateTime("2014-04-01"); // 3 months from now
echo DateTime::difference(new \DateTime("2014-05-01"), new \DateTime("2014-04-01"); // 1 month ago
echo DateTime::difference(new \DateTime("2015-05-01"), new \DateTime("2014-04-01"); // 1 year ago
echo DateTime::difference(new \DateTime("2014-05-01"), new \DateTime("2016-04-01"); // 2 years from now

```

Currently we support following languages:
* [English](src/Coduo/PHPHumanizer/Resources/translations/difference.en.yml)
* [Polish](src/Coduo/PHPHumanizer/Resources/translations/difference.pl.yml)

# Credits

This lib was inspired by [Java Humanize Lib](https://github.com/mfornos/humanize) && [Rails Active Support](https://github.com/rails/rails/tree/master/activesupport/lib/active_support)
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
],
"require": {
"php": ">=5.3.0",
"symfony/intl": "~2.3"
"symfony/intl": "~2.3",
"symfony/config": "~2.3",
"symfony/translation": "~2.3"
},
"require-dev": {
"phpspec/phpspec": "2.0.*"
Expand Down
106 changes: 106 additions & 0 deletions spec/Coduo/PHPHumanizer/DateTime/DifferenceSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace spec\Coduo\PHPHumanizer\DateTime;

use Coduo\PHPHumanizer\DateTime\Unit;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class DifferenceSpec extends ObjectBehavior
{
function it_calculate_diff_between_present_and_past_date_in_minutes()
{
$this->beConstructedWith(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 12:45:00"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Minute');
$this->getQuantity()->shouldReturn(15);
$this->isPast()->shouldReturn(true);
}

function it_calculate_diff_between_present_and_future_date_in_minutes()
{
$this->beConstructedWith(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 13:15:00"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Minute');
$this->getQuantity()->shouldReturn(15);
$this->isPast()->shouldReturn(false);
}

function it_calculate_diff_between_present_and_past_date_in_hours()
{
$this->beConstructedWith(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 11:00:00"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Hour');
$this->getQuantity()->shouldReturn(2);
$this->isPast()->shouldReturn(true);
}

function it_calculate_diff_between_present_and_future_date_in_hours()
{
$this->beConstructedWith(new \DateTime("2014-04-26 13:00:00"), new \DateTime("2014-04-26 16:00:00"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Hour');
$this->getQuantity()->shouldReturn(3);
$this->isPast()->shouldReturn(false);
}

function it_calculate_diff_between_present_and_past_date_in_days()
{
$this->beConstructedWith(new \DateTime("2014-04-10"), new \DateTime("2014-04-09"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Day');
$this->getQuantity()->shouldReturn(1);
$this->isPast()->shouldReturn(true);
}

function it_calculate_diff_between_present_and_future_date_in_days()
{
$this->beConstructedWith(new \DateTime("2014-04-10"), new \DateTime("2014-04-11"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Day');
$this->getQuantity()->shouldReturn(1);
$this->isPast()->shouldReturn(false);
}

function it_calculate_diff_between_present_and_past_date_in_weeks()
{
$this->beConstructedWith(new \DateTime("2014-04-15"), new \DateTime("2014-04-01"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Week');
$this->getQuantity()->shouldReturn(2);
$this->isPast()->shouldReturn(true);
}

function it_calculate_diff_between_present_and_future_date_in_weeks()
{
$this->beConstructedWith(new \DateTime("2014-04-01"), new \DateTime("2014-04-15"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Week');
$this->getQuantity()->shouldReturn(2);
$this->isPast()->shouldReturn(false);
}

function it_calculate_diff_between_present_and_past_date_in_months()
{
$this->beConstructedWith(new \DateTime("2014-04-01"), new \DateTime("2014-03-01"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Month');
$this->getQuantity()->shouldReturn(1);
$this->isPast()->shouldReturn(true);
}

function it_calculate_diff_between_present_and_future_date_in_months()
{
$this->beConstructedWith(new \DateTime("2014-04-01"), new \DateTime("2014-05-01"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Month');
$this->getQuantity()->shouldReturn(1);
$this->isPast()->shouldReturn(false);
}

function it_calculate_diff_between_present_and_past_date_in_years()
{
$this->beConstructedWith(new \DateTime("2014-01-01"), new \DateTime("2012-01-01"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Year');
$this->getQuantity()->shouldReturn(2);
$this->isPast()->shouldReturn(true);
}

function it_calculate_diff_between_present_and_future_date_in_years()
{
$this->beConstructedWith(new \DateTime("2014-01-01"), new \DateTime("2015-01-01"));
$this->getUnit()->shouldReturnAnInstanceOf('Coduo\PHPHumanizer\DateTime\Unit\Year');
$this->getQuantity()->shouldReturn(1);
$this->isPast()->shouldReturn(false);
}
}
48 changes: 48 additions & 0 deletions spec/Coduo/PHPHumanizer/DateTime/FormatterSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace spec\Coduo\PHPHumanizer\DateTime;

use Coduo\PHPHumanizer\DateTime\Difference;
use Coduo\PHPHumanizer\DateTime\Unit\Minute;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\Translation\Translator;

class FormatterSpec extends ObjectBehavior
{
function let(Translator $translator)
{
$this->beConstructedWith($translator);
$translator->transChoice(
'minute.past',
10,
array('%count%' => 10),
'difference',
'en'
)->willReturn('10 minutes ago');

$translator->transChoice(
'minute.past',
10,
array('%count%' => 10),
'difference',
'pl'
)->willReturn('10 minut temu');
}

function it_format_datetime_diff(Difference $diff)
{
$diff->getUnit()->willReturn(new Minute());
$diff->getQuantity()->willReturn(10);
$diff->isPast()->willReturn(true);
$this->formatDifference($diff)->shouldReturn('10 minutes ago');
}

function it_format_datetime_diff_for_specific_locale(Difference $diff)
{
$diff->getUnit()->willReturn(new Minute());
$diff->getQuantity()->willReturn(10);
$diff->isPast()->willReturn(true);
$this->formatDifference($diff, 'pl')->shouldReturn('10 minut temu');
}
}
66 changes: 66 additions & 0 deletions spec/Coduo/PHPHumanizer/DateTimeSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace spec\Coduo\PHPHumanizer;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class DateTimeSpec extends ObjectBehavior
{
function it_humanize_difference_between_dates()
{
$examples = array(
array("2014-04-26 13:00:00", "2014-04-26 13:00:00", 'just now'),
array("2014-04-26 13:00:00", "2014-04-26 13:00:05", '5 seconds from now'),
array("2014-04-26 13:00:00", "2014-04-26 12:59:00", '1 minute ago'),
array("2014-04-26 13:00:00", "2014-04-26 12:45:00", '15 minutes ago'),
array("2014-04-26 13:00:00", "2014-04-26 13:15:00", '15 minutes from now'),
array("2014-04-26 13:00:00", "2014-04-26 14:00:00", '1 hour from now'),
array("2014-04-26 13:00:00", "2014-04-26 15:00:00", '2 hours from now'),
array("2014-04-26 13:00:00", "2014-04-26 12:00:00", '1 hour ago'),
array("2014-04-26", "2014-04-25", '1 day ago'),
array("2014-04-26", "2014-04-24", '2 days ago'),
array("2014-04-26", "2014-04-28", '2 days from now'),
array("2014-04-01", "2014-04-15", '2 weeks from now'),
array("2014-04-15", "2014-04-07", '1 week ago'),
array("2014-01-01", "2014-04-01", '3 months from now'),
array("2014-05-01", "2014-04-01", '1 month ago'),
array("2015-05-01", "2014-04-01", '1 year ago'),
array("2014-05-01", "2016-04-01", '2 years from now'),
);

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

function it_humanize_difference_between_dates_for_pl_locale()
{
$examples = array(
array("2014-04-26 13:00:00", "2014-04-26 13:00:00", 'w tym momencie'),
array("2014-04-26 13:00:00", "2014-04-26 13:00:05", 'za 5 sekund'),
array("2014-04-26 13:00:00", "2014-04-26 12:59:00", 'minutę temu'),
array("2014-04-26 13:00:00", "2014-04-26 12:45:00", '15 minut temu'),
array("2014-04-26 13:00:00", "2014-04-26 13:15:00", 'za 15 minut'),
array("2014-04-26 13:00:00", "2014-04-26 14:00:00", 'za godzinę'),
array("2014-04-26 13:00:00", "2014-04-26 15:00:00", 'za 2 godziny'),
array("2014-04-26 13:00:00", "2014-04-26 12:00:00", 'godzinę temu'),
array("2014-04-26 13:00:00", "2014-04-26 15:00:00", 'za 2 godziny'),
array("2014-04-26 13:00:00", "2014-04-26 12:00:00", 'godzinę temu'),
array("2014-04-26", "2014-04-25", 'wczoraj'),
array("2014-04-26", "2014-04-24", '2 dni temu'),
array("2014-04-26", "2014-04-28", 'za 2 dni'),
array("2014-04-01", "2014-04-15", 'za 2 tygodnie'),
array("2014-04-15", "2014-04-07", 'tydzień temu'),
array("2014-01-01", "2014-04-01", 'za 3 miesiące'),
array("2014-05-01", "2014-04-01", 'miesiąc temu'),
array("2015-05-01", "2014-04-01", 'rok temu'),
array("2014-05-01", "2016-04-01", 'za 2 lata'),
array("2014-05-01", "2009-04-01", '5 lat temu'),
);

foreach ($examples as $example) {
$this->difference(new \DateTime($example[0]), new \DateTime($example[1]), 'pl')->shouldReturn($example[2]);
}
}
}
16 changes: 16 additions & 0 deletions src/Coduo/PHPHumanizer/DateTime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Coduo\PHPHumanizer;

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

class DateTime
{
public static function difference(\DateTime $fromDate, \DateTime $toDate, $locale = 'en')
{
$formatter = new Formatter(Builder::build($locale));
return $formatter->formatDifference(new Difference($fromDate, $toDate), $locale);
}
}
92 changes: 92 additions & 0 deletions src/Coduo/PHPHumanizer/DateTime/Difference.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?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;

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

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

/**
* @var \Coduo\PHPHumanizer\DateTime\Unit
*/
private $unit;

/**
* @var int
*/
private $quantity;

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

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

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

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(),
new JustNow()
);

$absoluteMilliSecondsDiff = abs($this->toDate->getTimestamp() - $this->fromDate->getTimestamp()) * 1000;
foreach ($units as $unit) {
if ($absoluteMilliSecondsDiff >= $unit->getMilliseconds()) {
$this->unit = $unit;
break;
}
}


$this->quantity = ($absoluteMilliSecondsDiff == 0)
? $absoluteMilliSecondsDiff
: (int) round($absoluteMilliSecondsDiff / $this->unit->getMilliseconds());
}

public function isPast()
{
$diff = $this->toDate->getTimestamp() - $this->fromDate->getTimestamp();
return ($diff > 0) ? false : true;
}
}
Loading

0 comments on commit 7438be8

Please sign in to comment.