Skip to content

Commit 3dc4200

Browse files
author
Bohdan Korablov
committed
MAGETWO-94196: [2.1] The fix of incorrect date format was lost since 2.1.13
1 parent 6089992 commit 3dc4200

File tree

3 files changed

+312
-38
lines changed

3 files changed

+312
-38
lines changed

dev/tests/integration/testsuite/Magento/Customer/Controller/Account/CreatePostTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected function setUp()
2626
}
2727

2828
/**
29-
* @magentoDbIsolation enabled
29+
* @magentoDbIsolation disabled
3030
* @magentoDataFixture Magento/Customer/_files/date_attribute.php
3131
* @magentoDataFixture Magento/Customer/_files/customer_date_attribute.php
3232
*/

lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
/**
1212
* Timezone library
13+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1314
*/
1415
class Timezone implements TimezoneInterface
1516
{
@@ -110,11 +111,21 @@ public function getConfigTimezone($scopeType = null, $scopeCode = null)
110111
*/
111112
public function getDateFormat($type = \IntlDateFormatter::SHORT)
112113
{
113-
return (new \IntlDateFormatter(
114+
$pattern = (new \IntlDateFormatter(
114115
$this->_localeResolver->getLocale(),
115116
$type,
116117
\IntlDateFormatter::NONE
117118
))->getPattern();
119+
120+
/**
121+
* This replacement is a workaround to prevent bugs in some third party libraries,
122+
* that works incorrectly with 'yyyy' value.
123+
* According to official doc of the ICU library
124+
* internally used in \Intl, 'yyyy' and 'y' formats are the same
125+
* @see http://userguide.icu-project.org/formatparse/datetime
126+
*/
127+
$pattern = str_replace('yyyy', 'y', $pattern);
128+
return $pattern;
118129
}
119130

120131
/**
@@ -151,7 +162,6 @@ public function getDateTimeFormat($type)
151162

152163
/**
153164
* {@inheritdoc}
154-
* @SuppressWarnings(PHPMD.NPathComplexity)
155165
*/
156166
public function date($date = null, $locale = null, $useTimezone = true, $includeTime = true)
157167
{
@@ -164,19 +174,52 @@ public function date($date = null, $locale = null, $useTimezone = true, $include
164174
return new \DateTime('now', new \DateTimeZone($timezone));
165175
} elseif ($date instanceof \DateTime) {
166176
return $date->setTimezone(new \DateTimeZone($timezone));
177+
} elseif ($date instanceof \DateTimeImmutable) {
178+
return new \DateTime($date->format('Y-m-d H:i:s'), $date->getTimezone());
167179
} elseif (!is_numeric($date)) {
168-
$timeType = $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE;
169-
$formatter = new \IntlDateFormatter(
170-
$locale,
171-
\IntlDateFormatter::SHORT,
172-
$timeType,
173-
new \DateTimeZone($timezone)
174-
);
175-
$date = $formatter->parse($date) ?: (new \DateTime($date))->getTimestamp();
180+
$date = $this->prepareDate($date, $locale, $timezone, $includeTime);
176181
}
182+
177183
return (new \DateTime(null, new \DateTimeZone($timezone)))->setTimestamp($date);
178184
}
179185

186+
/**
187+
* Convert string date according to locale format
188+
*
189+
* @param string $date
190+
* @param string $locale
191+
* @param string $timezone
192+
* @param bool $includeTime
193+
* @return string
194+
*/
195+
private function prepareDate(string $date, string $locale, string $timezone, bool $includeTime) : string
196+
{
197+
$timeType = $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE;
198+
$formatter = new \IntlDateFormatter(
199+
$locale,
200+
\IntlDateFormatter::SHORT,
201+
$timeType,
202+
new \DateTimeZone($timezone)
203+
);
204+
205+
/**
206+
* IntlDateFormatter does not parse correctly date formats per some locales
207+
* It depends on ICU lib version used by intl extension
208+
* For locales like fr_FR, ar_KW parse date with hyphen as separator
209+
*/
210+
if ($includeTime) {
211+
$date = $this->appendTimeIfNeeded($date);
212+
}
213+
try {
214+
$date = $formatter->parse($date) ?: (new \DateTime($date))->getTimestamp();
215+
} catch (\Exception $e) {
216+
$date = str_replace('/', '-', $date);
217+
$date = $formatter->parse($date) ?: (new \DateTime($date))->getTimestamp();
218+
}
219+
220+
return $date;
221+
}
222+
180223
/**
181224
* {@inheritdoc}
182225
*/
@@ -197,7 +240,7 @@ public function formatDate($date = null, $format = \IntlDateFormatter::SHORT, $s
197240
{
198241
$formatTime = $showTime ? $format : \IntlDateFormatter::NONE;
199242

200-
if (!($date instanceof \DateTime)) {
243+
if (!($date instanceof \DateTimeInterface)) {
201244
$date = new \DateTime($date);
202245
}
203246

@@ -234,21 +277,17 @@ public function isScopeDateInInterval($scope, $dateFrom = null, $dateTo = null)
234277
$toTimeStamp += 86400;
235278
}
236279

237-
$result = false;
238-
if (!$this->_dateTime->isEmptyDate($dateFrom) && $scopeTimeStamp < $fromTimeStamp) {
239-
} elseif (!$this->_dateTime->isEmptyDate($dateTo) && $scopeTimeStamp > $toTimeStamp) {
240-
} else {
241-
$result = true;
242-
}
280+
$result = !(!$this->_dateTime->isEmptyDate($dateFrom) && $scopeTimeStamp < $fromTimeStamp)
281+
&& !(!$this->_dateTime->isEmptyDate($dateTo) && $scopeTimeStamp > $toTimeStamp);
243282
return $result;
244283
}
245284

246285
/**
247286
* @param string|\DateTimeInterface $date
248287
* @param int $dateType
249288
* @param int $timeType
250-
* @param null $locale
251-
* @param null $timezone
289+
* @param string|null $locale
290+
* @param string|null $timezone
252291
* @param string|null $pattern
253292
* @return string
254293
*/
@@ -260,7 +299,7 @@ public function formatDateTime(
260299
$timezone = null,
261300
$pattern = null
262301
) {
263-
if (!($date instanceof \DateTime)) {
302+
if (!($date instanceof \DateTimeInterface)) {
264303
$date = new \DateTime($date);
265304
}
266305

@@ -296,8 +335,12 @@ public function formatDateTime(
296335
*/
297336
public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s')
298337
{
299-
if (!($date instanceof \DateTime)) {
300-
$date = new \DateTime($date, new \DateTimeZone($this->getConfigTimezone()));
338+
if (!($date instanceof \DateTimeInterface)) {
339+
if ($date instanceof \DateTimeImmutable) {
340+
$date = new \DateTime($date->format('Y-m-d H:i:s'), new \DateTimeZone($this->getConfigTimezone()));
341+
} else {
342+
$date = new \DateTime($date, new \DateTimeZone($this->getConfigTimezone()));
343+
}
301344
} else {
302345
if ($date->getTimezone()->getName() !== $this->getConfigTimezone()) {
303346
throw new LocalizedException(
@@ -310,4 +353,18 @@ public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s')
310353

311354
return $date->format($format);
312355
}
313-
}
356+
357+
/**
358+
* Add time in case if no time provided but required
359+
*
360+
* @param string $date
361+
* @return string
362+
*/
363+
private function appendTimeIfNeeded(string $date) : string
364+
{
365+
if (!preg_match('/\d{1,2}:\d{2}/', $date)) {
366+
$date .= " 00:00";
367+
}
368+
return $date;
369+
}
370+
}

0 commit comments

Comments
 (0)