/lib/Doctrine/ODM/MongoDB/Types/DateType.php

http://github.com/doctrine/mongodb-odm · PHP · 114 lines · 82 code · 18 blank · 14 comment · 7 complexity · af7d193001119fba48fb2659cee928bf MD5 · raw file

  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\ODM\MongoDB\Types;
  4. use DateTime;
  5. use DateTimeInterface;
  6. use DateTimeZone;
  7. use InvalidArgumentException;
  8. use MongoDB\BSON\UTCDateTime;
  9. use Throwable;
  10. use const STR_PAD_LEFT;
  11. use function abs;
  12. use function date_default_timezone_get;
  13. use function gettype;
  14. use function is_numeric;
  15. use function is_scalar;
  16. use function is_string;
  17. use function round;
  18. use function sprintf;
  19. use function str_pad;
  20. /**
  21. * The Date type.
  22. */
  23. class DateType extends Type
  24. {
  25. /**
  26. * Converts a value to a DateTime.
  27. * Supports microseconds
  28. *
  29. * @param mixed $value \DateTimeInterface|\MongoDB\BSON\UTCDateTime|int|float
  30. *
  31. * @throws InvalidArgumentException If $value is invalid.
  32. */
  33. public static function getDateTime($value) : DateTimeInterface
  34. {
  35. $datetime = false;
  36. $exception = null;
  37. if ($value instanceof DateTimeInterface) {
  38. return $value;
  39. }
  40. if ($value instanceof UTCDateTime) {
  41. $datetime = $value->toDateTime();
  42. $datetime->setTimezone(new DateTimeZone(date_default_timezone_get()));
  43. } elseif (is_numeric($value)) {
  44. $value = (float) $value;
  45. $seconds = (int) $value;
  46. $microseconds = abs(round($value - $seconds, 6));
  47. $microseconds *= 1000000;
  48. $datetime = static::craftDateTime($seconds, (int) $microseconds);
  49. } elseif (is_string($value)) {
  50. try {
  51. $datetime = new DateTime($value);
  52. } catch (Throwable $e) {
  53. $exception = $e;
  54. }
  55. }
  56. if ($datetime === false) {
  57. throw new InvalidArgumentException(sprintf('Could not convert %s to a date value', is_scalar($value) ? '"' . $value . '"' : gettype($value)), 0, $exception);
  58. }
  59. return $datetime;
  60. }
  61. /**
  62. * @return DateTime|false
  63. */
  64. private static function craftDateTime(int $seconds, int $microseconds = 0)
  65. {
  66. $datetime = new DateTime();
  67. $datetime->setTimestamp($seconds);
  68. if ($microseconds > 0) {
  69. $datetime = DateTime::createFromFormat('Y-m-d H:i:s.u', $datetime->format('Y-m-d H:i:s') . '.' . str_pad((string) $microseconds, 6, '0', STR_PAD_LEFT));
  70. }
  71. return $datetime;
  72. }
  73. public function convertToDatabaseValue($value)
  74. {
  75. if ($value === null || $value instanceof UTCDateTime) {
  76. return $value;
  77. }
  78. $datetime = static::getDateTime($value);
  79. return new UTCDateTime((int) $datetime->format('Uv'));
  80. }
  81. public function convertToPHPValue($value)
  82. {
  83. if ($value === null) {
  84. return null;
  85. }
  86. return static::getDateTime($value);
  87. }
  88. public function closureToMongo() : string
  89. {
  90. return 'if ($value === null || $value instanceof \MongoDB\BSON\UTCDateTime) { $return = $value; } else { $datetime = \\' . static::class . '::getDateTime($value); $return = new \MongoDB\BSON\UTCDateTime((int) $datetime->format(\'Uv\')); }';
  91. }
  92. public function closureToPHP() : string
  93. {
  94. return 'if ($value === null) { $return = null; } else { $return = \\' . static::class . '::getDateTime($value); }';
  95. }
  96. }