Skip to content

Instantly share code, notes, and snippets.

@zemd
Last active August 29, 2015 14:18
Show Gist options
  • Select an option

  • Save zemd/d086e86f20ed74c1782e to your computer and use it in GitHub Desktop.

Select an option

Save zemd/d086e86f20ed74c1782e to your computer and use it in GitHub Desktop.
Fixing storing dates' milliseconds in mongodb with DoctrineODM
<?php
namespace Opesho\CommonBundle\Doctrine\ODM\MongoDB\Types;
use Doctrine\ODM\MongoDB\Types\Type;
use Opesho\CommonBundle\Utils\DateUtils;
class DateType extends Type
{
public function convertToDatabaseValue($value)
{
if ($value === null) {
return null;
}
if ($value instanceof \MongoDate) {
return $value;
}
if ($value instanceof \DateTime) {
return new \MongoDate(intval($value->format("U")), intval($value->format("u")));
} elseif (is_numeric($value)) {
list($sec, $usec) = DateUtils::getSecUsec($value);
return new \MongoDate($sec, $usec);
} elseif (is_string($value)) {
$datetime = new \DateTime($value, new \DateTimeZone("UTC"));
if ($datetime === false) {
throw new \InvalidArgumentException(sprintf("Could not convert %s to a date value", is_scalar($value) ? '"' . $value . '"' : gettype($value)));
}
return new \MongoDate(intval($datetime->format("U")), intval($datetime->format("u")));
}
}
public function convertToPHPValue($value)
{
if ($value === null) {
return null;
}
if ($value instanceof \MongoDate) {
return new \DateTime(date("Y-m-d H:i:s.", $value->sec) . $value->usec, new \DateTimeZone("UTC"));
} elseif (is_numeric($value)) {
list($sec, $usec) = DateUtils::getSecUsec($value);
return new \DateTime(date("Y-m-d H:i:s.", $sec) . $usec, new \DateTimeZone("UTC"));
} elseif ($value instanceof \DateTime) {
return $value;
}
return new \DateTime($value, new \DateTimeZone("UTC"));
}
public function closureToMongo()
{
return 'if ($value instanceof \MongoDate) {
$return = $value;
} else if ($value instanceof \DateTime) {
$return = new \MongoDate(intval($value->format("U")), intval($value->format("u")));
} elseif (is_numeric($value)) {
list($sec, $usec) = \Opesho\CommonBundle\Utils\DateUtils::getSecUsec($value);
$return = new \MongoDate($sec, $usec);
} elseif (is_string($value)) {
$datetime = new \DateTime($value, new \DateTimeZone("UTC"));
$return = new \MongoDate(intval($datetime->format("U")), intval($datetime->format("u")));
}';
}
public function closureToPHP()
{
return 'if ($value instanceof \MongoDate) {
$return = new \DateTime(date("Y-m-d H:i:s.", $value->sec) . $value->usec, new \DateTimeZone("UTC"));
} elseif (is_numeric($value)) {
list($sec, $usec) = \Opesho\CommonBundle\Utils\DateUtils::getSecUsec($value);
$return = new \DateTime(date("Y-m-d H:i:s.", $sec) . $usec, new \DateTimeZone("UTC"));
} elseif ($value instanceof \DateTime) {
$return = $value;
} else {
$return = new \DateTime($value, new \DateTimeZone("UTC"));
}';
}
}
<?php
namespace Opesho\CommonBundle\Utils;
use DateTime;
/**
* Utils for datetime manipulating
*/
final class DateUtils
{
/**
* Helper for creating microseconds aware \DateTime objects. Useful for storing dates in mongo
*
* @param string $value
* @return DateTime
*/
public static function getDate($value = "now")
{
$micro = explode(" ", microtime());
$micros = substr($micro[0], 1, 7);
return new DateTime(date('Y-m-d H:i:s', strtotime($value)) . $micros, new \DateTimeZone("UTC"));
}
/**
* Returns array with two values of seconds and milliseconds or microseconds
*
* @param int $value
* @return array
*/
public static function getSecUsec($value)
{
$value = intval($value);
$sec = $value;
$usec = 0;
if ($value >= 100000000000000) {
// supposed the value is microseconds
$sec = intval($value / 1000000);
$usec = $value % 1000000;
} else if ($value >= 100000000000) {
// supposed the value is milliseconds
$sec = intval($value / 1000);
$usec = $value % 1000;
}
// else the value is seconds
return [$sec, $usec];
}
}
<?php
namespace Opesho\CommonBundle;
use Doctrine\ODM\MongoDB\Types\Type;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class OpeshoCommonBundle extends Bundle
{
public function __construct() {
Type::overrideType(Type::DATE, '\Opesho\CommonBundle\Doctrine\ODM\MongoDB\Types\DateType');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment