Skip to content

Commit fad16ab

Browse files
committed
PHPORM-234 Convert dates in DB Query results
1 parent 5b7ca02 commit fad16ab

File tree

4 files changed

+40
-15
lines changed

4 files changed

+40
-15
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
66
* Remove support for Laravel 10 by @GromNaN in [#3123](https://github.com/mongodb/laravel-mongodb/pull/3123)
77
* **BREAKING CHANGE** Use `id` as an alias for `_id` in commands and queries for compatibility with Eloquent packages by @GromNaN in [#3040](https://github.com/mongodb/laravel-mongodb/pull/3040)
88
* **BREAKING CHANGE** Make Query\Builder return objects instead of array to match Laravel behavior by @GromNaN in [#3107](https://github.com/mongodb/laravel-mongodb/pull/3107)
9+
* **BREAKING CHANGE** In DB query results, convert BSON `UTCDateTime` objects into `Carbon` date with the default timezone by @GromNaN in [#3119](https://github.com/mongodb/laravel-mongodb/pull/3119)
910
* Remove `MongoFailedJobProvider`, replaced by Laravel `DatabaseFailedJobProvider` by @GromNaN in [#3122](https://github.com/mongodb/laravel-mongodb/pull/3122)
1011

1112
## [4.8.0] - 2024-08-27

Diff for: src/Eloquent/DocumentModel.php

+18-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
namespace MongoDB\Laravel\Eloquent;
66

77
use BackedEnum;
8+
use Carbon\Carbon;
89
use Carbon\CarbonInterface;
910
use DateTimeInterface;
1011
use DateTimeZone;
1112
use Illuminate\Contracts\Queue\QueueableCollection;
1213
use Illuminate\Contracts\Queue\QueueableEntity;
1314
use Illuminate\Contracts\Support\Arrayable;
15+
use Illuminate\Database\Eloquent\Concerns\HasAttributes;
1416
use Illuminate\Database\Eloquent\Model;
1517
use Illuminate\Database\Eloquent\Relations\Relation;
1618
use Illuminate\Support\Arr;
@@ -97,8 +99,14 @@ public function getQualifiedKeyName()
9799
return $this->getKeyName();
98100
}
99101

100-
/** @inheritdoc */
101-
public function fromDateTime($value)
102+
/**
103+
* Convert a DateTime to a storable UTCDateTime.
104+
*
105+
* @see HasAttributes::fromDateTime()
106+
*
107+
* @param mixed $value
108+
*/
109+
public function fromDateTime($value): UTCDateTime
102110
{
103111
// If the value is already a UTCDateTime instance, we don't need to parse it.
104112
if ($value instanceof UTCDateTime) {
@@ -113,8 +121,14 @@ public function fromDateTime($value)
113121
return new UTCDateTime($value);
114122
}
115123

116-
/** @inheritdoc */
117-
protected function asDateTime($value)
124+
/**
125+
* Return a timestamp as DateTime object.
126+
*
127+
* @see HasAttributes::asDateTime()
128+
*
129+
* @param mixed $value
130+
*/
131+
protected function asDateTime($value): Carbon
118132
{
119133
// Convert UTCDateTime instances to Carbon.
120134
if ($value instanceof UTCDateTime) {

Diff for: src/Query/Builder.php

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Illuminate\Support\Arr;
1515
use Illuminate\Support\Carbon;
1616
use Illuminate\Support\Collection;
17+
use Illuminate\Support\Facades\Date;
1718
use Illuminate\Support\LazyCollection;
1819
use InvalidArgumentException;
1920
use LogicException;
@@ -1660,7 +1661,9 @@ private function aliasIdForResult(array|object $values): array|object
16601661
}
16611662

16621663
foreach ($values as $key => $value) {
1663-
if (is_array($value) || is_object($value)) {
1664+
if ($value instanceof UTCDateTime) {
1665+
$values[$key] = Date::instance($value->toDateTime());
1666+
} elseif (is_array($value) || $value instanceof stdClass) {
16641667
$values[$key] = $this->aliasIdForResult($value);
16651668
}
16661669
}
@@ -1673,7 +1676,9 @@ private function aliasIdForResult(array|object $values): array|object
16731676
}
16741677

16751678
foreach (get_object_vars($values) as $key => $value) {
1676-
if (is_array($value) || is_object($value)) {
1679+
if ($value instanceof UTCDateTime) {
1680+
$values->{$key} = Date::instance($value->toDateTime());
1681+
} elseif (is_array($value) || $value instanceof stdClass) {
16771682
$values->{$key} = $this->aliasIdForResult($value);
16781683
}
16791684
}

Diff for: tests/QueryBuilderTest.php

+14-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace MongoDB\Laravel\Tests;
66

7+
use Carbon\Carbon;
78
use DateTime;
89
use DateTimeImmutable;
910
use Illuminate\Support\Facades\Date;
@@ -33,7 +34,6 @@
3334
use function md5;
3435
use function sort;
3536
use function strlen;
36-
use function strtotime;
3737

3838
class QueryBuilderTest extends TestCase
3939
{
@@ -676,27 +676,32 @@ public function testUpdateSubdocument()
676676
public function testDates()
677677
{
678678
DB::table('users')->insert([
679-
['name' => 'John Doe', 'birthday' => new UTCDateTime(Date::parse('1980-01-01 00:00:00'))],
680-
['name' => 'Robert Roe', 'birthday' => new UTCDateTime(Date::parse('1982-01-01 00:00:00'))],
681-
['name' => 'Mark Moe', 'birthday' => new UTCDateTime(Date::parse('1983-01-01 00:00:00.1'))],
682-
['name' => 'Frank White', 'birthday' => new UTCDateTime(Date::parse('1960-01-01 12:12:12.1'))],
679+
['name' => 'John Doe', 'birthday' => Date::parse('1980-01-01 00:00:00')],
680+
['name' => 'Robert Roe', 'birthday' => Date::parse('1982-01-01 00:00:00')],
681+
['name' => 'Mark Moe', 'birthday' => Date::parse('1983-01-01 00:00:00.1')],
682+
['name' => 'Frank White', 'birthday' => Date::parse('1975-01-01 12:12:12.1')],
683683
]);
684684

685685
$user = DB::table('users')
686-
->where('birthday', new UTCDateTime(Date::parse('1980-01-01 00:00:00')))
686+
->where('birthday', Date::parse('1980-01-01 00:00:00'))
687687
->first();
688688
$this->assertEquals('John Doe', $user->name);
689689

690690
$user = DB::table('users')
691-
->where('birthday', new UTCDateTime(Date::parse('1960-01-01 12:12:12.1')))
691+
->where('birthday', Date::parse('1975-01-01 12:12:12.1'))
692692
->first();
693+
693694
$this->assertEquals('Frank White', $user->name);
695+
$this->assertInstanceOf(Carbon::class, $user->birthday);
696+
$this->assertSame('1975-01-01 12:12:12.100000', $user->birthday->format('Y-m-d H:i:s.u'));
694697

695698
$user = DB::table('users')->where('birthday', '=', new DateTime('1980-01-01 00:00:00'))->first();
696699
$this->assertEquals('John Doe', $user->name);
700+
$this->assertInstanceOf(Carbon::class, $user->birthday);
701+
$this->assertSame('1980-01-01 00:00:00.000000', $user->birthday->format('Y-m-d H:i:s.u'));
697702

698-
$start = new UTCDateTime(1000 * strtotime('1950-01-01 00:00:00'));
699-
$stop = new UTCDateTime(1000 * strtotime('1981-01-01 00:00:00'));
703+
$start = new UTCDateTime(new DateTime('1950-01-01 00:00:00'));
704+
$stop = new UTCDateTime(new DateTime('1981-01-01 00:00:00'));
700705

701706
$users = DB::table('users')->whereBetween('birthday', [$start, $stop])->get();
702707
$this->assertCount(2, $users);

0 commit comments

Comments
 (0)