Skip to content

Commit

Permalink
Add TimeUnitSpeller in Russian
Browse files Browse the repository at this point in the history
  • Loading branch information
wapmorgan committed Jul 12, 2017
1 parent 91f3e4b commit b294708
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 1 deletion.
26 changes: 25 additions & 1 deletion README-ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
* [Числительные](#Числительные)
* [Количественные числительные](#Количественные-числительные)
* [Порядковые числительные](#Порядковые-числительные)
* [Валюты](#Валюты)
* [Окончание глаголов](#Окончание-глаголов)
* [Валюты](#Валюты)
* [Временные интервалы](#Временные-интервалы)

Для русского языка доступны следующие функции:

Expand Down Expand Up @@ -336,3 +337,26 @@ $gender = morphos\Gender::FEMALE;
$name.' '.morphos\Russian\verb('добавил', $gender) => 'Анастасия добавила'
$name.' '.morphos\Russian\verb('поделился', $gender).' публикацией' => 'Анастасия поделилась публикацией'
```

## Временные интервалы

Класс `TimeUnitSpeller` позволяет записать человеческим языком временной интервал, задаваемый объектом `DateInterval`.

_Пример_

```php
use morphos\Russian\TimeUnitSpeller;

TimeUnitSpeller::spellInterval(new DateInterval('P5YT2M')) => '5 лет 2 часа'
```

Также можно передать вторым аргументом одну из следующих опций или их комбинацию (побитовое или `|`):

- `TimeUnitSpeller::DIRECTION` - добавляет "назад" для положительных интвералов и "через" для отрицательных.
- `TimeUnitSpeller::SEPARATE` - добавляет запятые между составными интервала и союз перед последней частью.

```php
TimeUnitSpeller::spellInterval(new DateInterval('P5YT2M'), TimeUnitSpeller::DIRECTION) => '5 лет 2 часа назад'
TimeUnitSpeller::spellInterval(new DateInterval('P5YT2M'), TimeUnitSpeller::SEPARATE) => '5 лет и 2 часа'
TimeUnitSpeller::spellInterval(new DateInterval('P5YT2M'), TimeUnitSpeller::DIRECTION | TimeUnitSpeller::SEPARATE) => '5 лет и 2 часа назад'
```
35 changes: 35 additions & 0 deletions src/Russian/TimeUnitSpeller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
namespace morphos\Russian;

use InvalidArgumentException;

class TimeUnitSpeller extends \morphos\TimeUnitSpeller
{
protected static $units = [
self::YEAR => 'год',
self::MONTH => 'месяц',
self::DAY => 'день',
self::HOUR => 'час',
self::MINUTE => 'минута',
self::SECOND => 'секунда',
];

const AGO = 'назад';
const IN = 'через';

const AND = 'и';

const JUST_NOW = 'только что';

public static function spellUnit($count, $unit)
{
if (!isset(self::$units[$unit]))
throw new InvalidArgumentException('Unknown time unit: '.$unit);

// special case for YEAR >= 5
if ($unit == self::YEAR && Plurality::getNumeralForm($count) == Plurality::FIVE_OTHER)
return $count.' лет';

return $count.' '.pluralize(self::$units[$unit], $count);
}
}
60 changes: 60 additions & 0 deletions src/TimeUnitSpeller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
namespace morphos;

use DateInterval;

abstract class TimeUnitSpeller
{
const YEAR = 'year';
const MONTH = 'month';
const DAY = 'day';
const HOUR = 'hour';
const MINUTE = 'minute';
const SECOND = 'second';

const AGO = 'ago';
const IN = 'in';

const AND = 'and';

const JUST_NOW = 'just now';

const DIRECTION = 1;
const SEPARATE = 2;

abstract public static function spellUnit($count, $unit);

public static function spellInterval(DateInterval $interval, $options = 0)
{
$parts = [];
foreach ([
'y' => self::YEAR,
'm' => self::MONTH,
'd' => self::DAY,
'h' => self::HOUR,
'i' => self::MINUTE,
's' => self::SECOND
] as $interval_field => $unit) {
if ($interval->{$interval_field} > 0)
$parts[] = static::spellUnit($interval->{$interval_field}, $unit);
}

if (empty($parts))
return static::JUST_NOW;

if ($options & self::SEPARATE && count($parts) > 1) {
$last_part = array_pop($parts);
$spelled = implode(', ', $parts).' '.static::AND.' '.$last_part;
} else
$spelled = implode(' ', $parts);

if ($options & self::DIRECTION) {
if ($interval->invert)
$spelled = static::IN.' '.$spelled;
else
$spelled .= ' '.static::AGO;
}

return $spelled;
}
}
51 changes: 51 additions & 0 deletions tests/Russian/TimeUnitSpellerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
namespace morphos\test\Russian;
require __DIR__.'/../../vendor/autoload.php';

use DateInterval;
use morphos\Russian\TimeUnitSpeller;

class TimeUnitSpellerTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider intervalsProvider()
*/
public function testSpellInterval($interval, $options, $result)
{
$this->assertEquals($result, TimeUnitSpeller::spellInterval(new DateInterval($interval), $options));
}

public function intervalsProvider()
{
return
[
['P1Y5M10D', 0, '1 год 5 месяцев 10 дней'],
['P10Y1MT5H', 0, '10 лет 1 месяц 5 часов'],
['P3DT1H2M', 0, '3 дня 1 час 2 минуты'],
['P10MT40M30S', 0, '10 месяцев 40 минут 30 секунд'],
['P1Y5M10D', TimeUnitSpeller::SEPARATE, '1 год, 5 месяцев и 10 дней'],
['P10Y1MT5H', TimeUnitSpeller::DIRECTION, '10 лет 1 месяц 5 часов назад'],
['P3DT1H2M', TimeUnitSpeller::SEPARATE | TimeUnitSpeller::DIRECTION, '3 дня, 1 час и 2 минуты назад'],
['P10MT40M30S', TimeUnitSpeller::SEPARATE, '10 месяцев, 40 минут и 30 секунд'],
];
}

/**
* @dataProvider timeUnitsProvider()
*/
public function testSpellUnit($value, $unit, $result)
{
$this->assertEquals($result, TimeUnitSpeller::spellUnit($value, $unit));
}

public function timeUnitsProvider()
{
return
[
[5, TimeUnitSpeller::YEAR, '5 лет'],
[5, TimeUnitSpeller::MONTH, '5 месяцев'],
[5, TimeUnitSpeller::HOUR, '5 часов'],
[5, TimeUnitSpeller::SECOND, '5 секунд'],
];
}
}

0 comments on commit b294708

Please sign in to comment.