Skip to content

Commit ec9f04b

Browse files
committed
Merge 3.x into 3.next
2 parents 7a3db17 + 960e7ec commit ec9f04b

2 files changed

Lines changed: 8 additions & 187 deletions

File tree

src/Chronos.php

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -692,98 +692,9 @@ public static function createFromFormat(
692692
throw new InvalidArgumentException($message);
693693
}
694694

695-
$testNow = static::getTestNow();
696-
if ($testNow !== null) {
697-
$dateTime = static::applyTestNowToMissingComponents($dateTime, $format, $testNow);
698-
}
699-
700695
return $dateTime;
701696
}
702697

703-
/**
704-
* Apply testNow values to date/time components that weren't in the format string.
705-
*
706-
* @param static $dateTime The parsed datetime instance.
707-
* @param string $format The format string used for parsing.
708-
* @param \Cake\Chronos\Chronos $testNow The test now instance.
709-
* @return static
710-
*/
711-
protected static function applyTestNowToMissingComponents(
712-
self $dateTime,
713-
string $format,
714-
Chronos $testNow,
715-
): static {
716-
// Parse format string to find which characters are actual format specifiers (not escaped)
717-
$formatChars = static::getFormatCharacters($format);
718-
719-
// Check which components are present in the format
720-
$hasYear = (bool)array_intersect($formatChars, ['Y', 'y', 'o', 'X', 'x']);
721-
$hasMonth = (bool)array_intersect($formatChars, ['m', 'n', 'M', 'F']);
722-
$hasDay = (bool)array_intersect($formatChars, ['d', 'j', 'D', 'l', 'N', 'z', 'w', 'W', 'S']);
723-
$hasHour = (bool)array_intersect($formatChars, ['H', 'G', 'h', 'g']);
724-
$hasMinute = (bool)array_intersect($formatChars, ['i']);
725-
$hasSecond = (bool)array_intersect($formatChars, ['s']);
726-
$hasMicro = (bool)array_intersect($formatChars, ['u', 'v']);
727-
728-
// If the format includes '!' or '|', PHP resets unspecified components to Unix epoch or zero
729-
// If 'U' is present, all components are set from the Unix timestamp
730-
// In these cases, we should not override with testNow
731-
$hasReset = in_array('!', $formatChars, true) || in_array('|', $formatChars, true);
732-
$hasUnixTimestamp = in_array('U', $formatChars, true);
733-
if ($hasReset || $hasUnixTimestamp) {
734-
return $dateTime;
735-
}
736-
737-
// Replace missing components with testNow values
738-
$year = $hasYear ? $dateTime->year : $testNow->year;
739-
$month = $hasMonth ? $dateTime->month : $testNow->month;
740-
$day = $hasDay ? $dateTime->day : $testNow->day;
741-
$hour = $hasHour ? $dateTime->hour : $testNow->hour;
742-
$minute = $hasMinute ? $dateTime->minute : $testNow->minute;
743-
$second = $hasSecond ? $dateTime->second : $testNow->second;
744-
$micro = $hasMicro ? $dateTime->micro : $testNow->micro;
745-
746-
// Only modify if something needs to change
747-
if (
748-
!$hasYear || !$hasMonth || !$hasDay ||
749-
!$hasHour || !$hasMinute || !$hasSecond || !$hasMicro
750-
) {
751-
return $dateTime
752-
->setDate($year, $month, $day)
753-
->setTime($hour, $minute, $second, $micro);
754-
}
755-
756-
return $dateTime;
757-
}
758-
759-
/**
760-
* Extract format characters from a format string, handling escapes.
761-
*
762-
* @param string $format The format string.
763-
* @return array<string> Array of format characters.
764-
*/
765-
protected static function getFormatCharacters(string $format): array
766-
{
767-
$chars = [];
768-
$length = strlen($format);
769-
$i = 0;
770-
771-
while ($i < $length) {
772-
$char = $format[$i];
773-
774-
// Backslash escapes the next character
775-
if ($char === '\\' && $i + 1 < $length) {
776-
$i += 2;
777-
continue;
778-
}
779-
780-
$chars[] = $char;
781-
$i++;
782-
}
783-
784-
return $chars;
785-
}
786-
787698
/**
788699
* Returns parse warnings and errors from the last ``createFromFormat()``
789700
* call.

tests/TestCase/DateTime/CreateFromFormatTest.php

Lines changed: 8 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -29,104 +29,6 @@ public function testCreateFromFormatReturnsInstance()
2929
$this->assertTrue($d instanceof Chronos);
3030
}
3131

32-
public function testCreateFromFormatWithTestNowMissingYear()
33-
{
34-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
35-
$d = Chronos::createFromFormat('m-d H:i:s', '10-05 09:15:30');
36-
$this->assertDateTime($d, 2020, 10, 5, 9, 15, 30);
37-
}
38-
39-
public function testCreateFromFormatWithTestNowMissingDate()
40-
{
41-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
42-
$d = Chronos::createFromFormat('H:i:s', '09:15:30');
43-
$this->assertDateTime($d, 2020, 12, 1, 9, 15, 30);
44-
}
45-
46-
public function testCreateFromFormatWithTestNowMissingTime()
47-
{
48-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
49-
$d = Chronos::createFromFormat('Y-m-d', '2021-06-15');
50-
$this->assertDateTime($d, 2021, 6, 15, 14, 30, 45);
51-
}
52-
53-
public function testCreateFromFormatWithTestNowPartialDate()
54-
{
55-
Chronos::setTestNow(new Chronos('2020-12-01 00:00:00'));
56-
$d = Chronos::createFromFormat('m-d', '10-05');
57-
$this->assertDateTime($d, 2020, 10, 5, 0, 0, 0);
58-
}
59-
60-
public function testCreateFromFormatWithTestNowDayOnly()
61-
{
62-
Chronos::setTestNow(new Chronos('2020-12-01 00:00:00'));
63-
$d = Chronos::createFromFormat('d', '05');
64-
$this->assertDateTime($d, 2020, 12, 5, 0, 0, 0);
65-
}
66-
67-
public function testCreateFromFormatWithTestNowComplete()
68-
{
69-
// When format is complete, testNow should not affect the result
70-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
71-
$d = Chronos::createFromFormat('Y-m-d H:i:s', '1975-05-21 22:32:11');
72-
$this->assertDateTime($d, 1975, 5, 21, 22, 32, 11);
73-
}
74-
75-
public function testCreateFromFormatWithTestNowResetModifier()
76-
{
77-
// The '!' modifier resets to Unix epoch, should not use testNow
78-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
79-
$d = Chronos::createFromFormat('!Y-m-d', '2021-06-15');
80-
$this->assertDateTime($d, 2021, 6, 15, 0, 0, 0);
81-
}
82-
83-
public function testCreateFromFormatWithTestNowPipeModifier()
84-
{
85-
// The '|' modifier resets unspecified components to zero, should not use testNow
86-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
87-
$d = Chronos::createFromFormat('Y-m-d|', '2021-06-15');
88-
$this->assertDateTime($d, 2021, 6, 15, 0, 0, 0);
89-
}
90-
91-
public function testCreateFromFormatWithoutTestNow()
92-
{
93-
// Without testNow set, behavior should use real current time for missing components
94-
Chronos::setTestNow(null);
95-
$d = Chronos::createFromFormat('Y-m-d H:i:s', '1975-05-21 22:32:11');
96-
$this->assertDateTime($d, 1975, 5, 21, 22, 32, 11);
97-
}
98-
99-
public function testCreateFromFormatWithTestNowEscapedCharacters()
100-
{
101-
// Escaped format characters should not be treated as format specifiers
102-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
103-
$d = Chronos::createFromFormat('\Y\-m-d', 'Y-10-05');
104-
$this->assertDateTime($d, 2020, 10, 5, 14, 30, 45);
105-
}
106-
107-
public function testCreateFromFormatWithTestNowMicroseconds()
108-
{
109-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45.123456'));
110-
$d = Chronos::createFromFormat('Y-m-d H:i:s', '2021-06-15 09:15:30');
111-
$this->assertSame(123456, $d->micro);
112-
}
113-
114-
public function testCreateFromFormatWithTestNowUnixTimestamp()
115-
{
116-
// Unix timestamp ('U' format) sets all components, should not use testNow
117-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
118-
$d = Chronos::createFromFormat('U', '0');
119-
$this->assertDateTime($d, 1970, 1, 1, 0, 0, 0);
120-
}
121-
122-
public function testCreateFromFormatWithTestNowNegativeUnixTimestamp()
123-
{
124-
// Negative Unix timestamp should also not use testNow
125-
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
126-
$d = Chronos::createFromFormat('U', '-1000');
127-
$this->assertDateTime($d, 1969, 12, 31, 23, 43, 20);
128-
}
129-
13032
public function testCreateFromFormatWithTimezoneString()
13133
{
13234
$d = Chronos::createFromFormat('Y-m-d H:i:s', '1975-05-21 22:32:11', 'Europe/London');
@@ -160,4 +62,12 @@ public function testCreateFromFormatInvalidFormat()
16062
$this->assertIsArray(Chronos::getLastErrors());
16163
$this->assertNotEmpty(Chronos::getLastErrors()['errors']);
16264
}
65+
66+
public function testCreateFromFormatDoesNotUseTestNow()
67+
{
68+
// createFromFormat should not use testNow - it should behave like PHP's native method
69+
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
70+
$d = Chronos::createFromFormat('Y-m-d H:i:s', '1975-05-21 22:32:11');
71+
$this->assertDateTime($d, 1975, 5, 21, 22, 32, 11);
72+
}
16373
}

0 commit comments

Comments
 (0)