add carbon lib for date operations

This commit is contained in:
DavidBadura 2015-02-08 11:23:14 +00:00
parent eee7c668cc
commit 9ed7f6ff7c
6 changed files with 185 additions and 34 deletions

View File

@ -17,7 +17,8 @@
"php": ">=5.4", "php": ">=5.4",
"symfony/process": "~2.3", "symfony/process": "~2.3",
"jms/serializer": "0.16.*", "jms/serializer": "0.16.*",
"symfony/filesystem": "~2.3" "symfony/filesystem": "~2.3",
"nesbot/carbon": "~1.14"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "~4.0" "phpunit/phpunit": "~4.0"

View File

@ -0,0 +1,108 @@
<?php
namespace DavidBadura\Taskwarrior\Serializer\Handler;
use Carbon\Carbon;
use JMS\Serializer\Context;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\VisitorInterface;
/**
* @author David Badura <d.a.badura@gmail.com>
*/
class CarbonHandler implements SubscribingHandlerInterface
{
/**
* @var string
*/
private $defaultFormat;
/**
* @var \DateTimeZone
*/
private $defaultTimezone;
/**
* @param string $defaultFormat
* @param string $defaultTimezone
*/
public function __construct($defaultFormat = 'Ymd\THis\Z', $defaultTimezone = 'UTC')
{
$this->defaultFormat = $defaultFormat;
$this->defaultTimezone = new \DateTimeZone($defaultTimezone);
}
/**
* @return array
*/
public static function getSubscribingMethods()
{
$methods = array();
$types = array('Carbon\Carbon', 'Carbon');
foreach ($types as $type) {
$methods[] = array(
'type' => $type,
'format' => 'json',
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
'method' => 'deserializeCarbon'
);
$methods[] = array(
'type' => $type,
'format' => 'json',
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'method' => 'serializeCarbon'
);
}
return $methods;
}
/**
* @param VisitorInterface $visitor
* @param Carbon $date
* @param array $type
* @param Context $context
* @return string
*/
public function serializeCarbon(VisitorInterface $visitor, Carbon $date, array $type, Context $context)
{
return $visitor->visitString($date->format($this->getFormat($type)), $type, $context);
}
/**
* @param VisitorInterface $visitor
* @param string $data
* @param array $type
* @return \DateTime|null
*/
public function deserializeCarbon(VisitorInterface $visitor, $data, array $type)
{
if (null === $data) {
return null;
}
$timezone = isset($type['params'][1]) ? new \DateTimeZone($type['params'][1]) : $this->defaultTimezone;
$format = $this->getFormat($type);
$datetime = Carbon::createFromFormat($format, (string)$data, $timezone);
if (false === $datetime) {
throw new RuntimeException(sprintf('Invalid datetime "%s", expected format %s.', $data, $format));
}
return $datetime;
}
/**
* @param array $type
* @return string
*/
private function getFormat(array $type)
{
return isset($type['params'][0]) ? $type['params'][0] : $this->defaultFormat;
}
}

View File

@ -2,6 +2,7 @@
namespace DavidBadura\Taskwarrior; namespace DavidBadura\Taskwarrior;
use Carbon\Carbon;
use JMS\Serializer\Annotation as JMS; use JMS\Serializer\Annotation as JMS;
/** /**
@ -47,23 +48,23 @@ class Task
private $project; private $project;
/** /**
* @var \DateTime * @var Carbon
* *
* @JMS\Type(name="DateTime<'Ymd\THis\Z'>") * @JMS\Type("Carbon")
*/ */
private $due; private $due;
/** /**
* @var \DateTime * @var Carbon
* *
* @JMS\Type(name="DateTime<'Ymd\THis\Z'>") * @JMS\Type("Carbon")
*/ */
private $wait; private $wait;
/** /**
* @var \DateTime * @var Carbon
* *
* @JMS\Type(name="DateTime<'Ymd\THis\Z'>") * @JMS\Type("Carbon")
*/ */
private $until; private $until;
@ -82,24 +83,24 @@ class Task
private $urgency; private $urgency;
/** /**
* @var \DateTime * @var Carbon
* *
* @JMS\Type(name="DateTime<'Ymd\THis\Z'>") * @JMS\Type("Carbon")
*/ */
private $entry; private $entry;
/** /**
* @var \DateTime * @var Carbon
* *
* @JMS\Type(name="DateTime<'Ymd\THis\Z'>") * @JMS\Type("Carbon")
*/ */
private $modified; private $modified;
/** /**
* @var \DateTime * @var Carbon
* *
* @JMS\Type(name="DateTime<'Ymd\THis\Z'>") * @JMS\Type("Carbon")
*/ */
private $end; private $end;
@ -116,7 +117,7 @@ class Task
public function __construct() public function __construct()
{ {
$this->urgency = 0; $this->urgency = 0;
$this->entry = new \DateTime('now', new \DateTimeZone('UTC')); $this->entry = new Carbon('now', new \DateTimeZone('UTC'));
$this->status = self::STATUS_PENDING; $this->status = self::STATUS_PENDING;
} }
@ -348,7 +349,10 @@ class Task
private function parseDateTime($date) private function parseDateTime($date)
{ {
if ($date instanceof \DateTime) { if ($date instanceof \DateTime) {
return new Carbon($date->format('Y-m-d H:i:s'), new \DateTimeZone('UTC'));
}
if ($date instanceof Carbon) {
$date = clone $date; $date = clone $date;
$date->setTimezone(new \DateTimeZone('UTC')); $date->setTimezone(new \DateTimeZone('UTC'));
@ -356,7 +360,7 @@ class Task
} }
if (is_string($date)) { if (is_string($date)) {
return new \DateTime($date, new \DateTimeZone('UTC')); return new Carbon($date, new \DateTimeZone('UTC'));
} }
if ($date === null) { if ($date === null) {
@ -372,7 +376,7 @@ class Task
public function __clone() public function __clone()
{ {
$this->uuid = null; $this->uuid = null;
$this->entry = new \DateTime('now', new \DateTimeZone('UTC')); $this->entry = new Carbon('now', new \DateTimeZone('UTC'));
$this->status = self::STATUS_PENDING; $this->status = self::STATUS_PENDING;
} }
} }

View File

@ -2,9 +2,10 @@
namespace DavidBadura\Taskwarrior; namespace DavidBadura\Taskwarrior;
use DavidBadura\Taskwarrior\Serializer\Handler\CarbonHandler;
use JMS\Serializer\Handler\HandlerRegistryInterface;
use JMS\Serializer\Serializer;
use JMS\Serializer\SerializerBuilder; use JMS\Serializer\SerializerBuilder;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\ProcessBuilder;
/** /**
* @author David Badura <d.a.badura@gmail.com> * @author David Badura <d.a.badura@gmail.com>
@ -164,11 +165,7 @@ class TaskManager
{ {
$json = $this->taskwarrior->export($filter); $json = $this->taskwarrior->export($filter);
$serializer = SerializerBuilder::create() return $this->getSerializer()->deserialize($json, 'array<DavidBadura\Taskwarrior\Task>', 'json');
->addDefaultHandlers()
->build();
return $serializer->deserialize($json, 'array<DavidBadura\Taskwarrior\Task>', 'json');
} }
/** /**
@ -241,11 +238,7 @@ class TaskManager
*/ */
private function serializeTask(Task $task) private function serializeTask(Task $task)
{ {
$serializer = SerializerBuilder::create() $result = $this->getSerializer()->serialize($task, 'json');
->addDefaultHandlers()
->build();
$result = $serializer->serialize($task, 'json');
return str_replace("\\/", "/", $result); return str_replace("\\/", "/", $result);
} }
@ -263,6 +256,20 @@ class TaskManager
$prop->setValue($task, $value); $prop->setValue($task, $value);
} }
/**
* @return Serializer
*/
private function getSerializer()
{
return SerializerBuilder::create()
->configureHandlers(function (HandlerRegistryInterface $registry) {
$registry->registerSubscribingHandler(new CarbonHandler());
})
->addDefaultHandlers()
->setDebug(true)
->build();
}
/** /**
* @return self * @return self
*/ */

View File

@ -16,6 +16,11 @@ class Taskwarrior
*/ */
private $rcOptions; private $rcOptions;
/**
* @var string
*/
private $version;
/** /**
* @param string $taskrc * @param string $taskrc
* @param string $taskData * @param string $taskData
@ -56,7 +61,7 @@ class Taskwarrior
*/ */
public function add(array $params) public function add(array $params)
{ {
$this->command('modify', null, $this->getOptions($params)); $this->command('add', null, $this->getOptions($params));
} }
/** /**
@ -173,7 +178,11 @@ class Taskwarrior
*/ */
public function version() public function version()
{ {
return $this->command('_version'); if ($this->version) {
return $this->version;
}
return $this->version = $this->command('_version');
} }
/** /**

View File

@ -176,8 +176,15 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
$this->assertCount(1, $this->taskManager->filter('project:home prio:H +now')); $this->assertCount(1, $this->taskManager->filter('project:home prio:H +now'));
} }
public function testDates() public function testModified()
{ {
if (version_compare($this->taskwarrior->version(), '2.2.0', '>=')) {
$this->markTestSkipped(sprintf(
'taskwarrior version %s dont support modified attr',
$this->taskwarrior->version()
));
}
$task1 = new Task(); $task1 = new Task();
$task1->setDescription('foo1'); $task1->setDescription('foo1');
@ -185,7 +192,6 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
$this->assertInstanceOf('DateTime', $task1->getEntry()); $this->assertInstanceOf('DateTime', $task1->getEntry());
$this->assertNull($task1->getModified()); $this->assertNull($task1->getModified());
$this->assertNull($task1->getEnd());
$task1->setDescription('bar2'); $task1->setDescription('bar2');
@ -193,12 +199,28 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
$this->assertInstanceOf('DateTime', $task1->getEntry()); $this->assertInstanceOf('DateTime', $task1->getEntry());
$this->assertInstanceOf('DateTime', $task1->getModified()); $this->assertInstanceOf('DateTime', $task1->getModified());
}
public function testEnd()
{
$task1 = new Task();
$task1->setDescription('foo1');
$this->taskManager->save($task1);
$this->assertInstanceOf('DateTime', $task1->getEntry());
$this->assertNull($task1->getEnd());
$task1->setDescription('bar2');
$this->taskManager->save($task1);
$this->assertInstanceOf('DateTime', $task1->getEntry());
$this->assertNull($task1->getEnd()); $this->assertNull($task1->getEnd());
$this->taskManager->done($task1); $this->taskManager->done($task1);
$this->assertInstanceOf('DateTime', $task1->getEntry()); $this->assertInstanceOf('DateTime', $task1->getEntry());
$this->assertInstanceOf('DateTime', $task1->getModified());
$this->assertInstanceOf('DateTime', $task1->getEnd()); $this->assertInstanceOf('DateTime', $task1->getEnd());
} }
@ -507,6 +529,6 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
*/ */
private function createDateTime($string = 'now') private function createDateTime($string = 'now')
{ {
return new \DateTime($string); return new \DateTime($string, new \DateTimeZone('UTC'));
} }
} }