@@ -30,6 +30,11 @@ class Timezone implements TimezoneInterface
30
30
\IntlDateFormatter::SHORT ,
31
31
];
32
32
33
+ /**
34
+ * @var array
35
+ */
36
+ private $ dateFormatterCache = [];
37
+
33
38
/**
34
39
* @var string
35
40
*/
@@ -174,16 +179,9 @@ public function date($date = null, $locale = null, $useTimezone = true, $include
174
179
case ($ date instanceof \DateTimeImmutable):
175
180
return new \DateTime ($ date ->format ('Y-m-d H:i:s ' ), $ date ->getTimezone ());
176
181
case (!is_numeric ($ date )):
177
- $ timeType = $ includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE ;
178
- $ formatter = new \IntlDateFormatter (
179
- $ locale ,
180
- \IntlDateFormatter::MEDIUM ,
181
- $ timeType ,
182
- new \DateTimeZone ($ timezone )
183
- );
184
-
185
182
$ date = $ this ->appendTimeIfNeeded ($ date , $ includeTime , $ timezone , $ locale );
186
- $ date = $ formatter ->parse ($ date ) ?: (new \DateTime ($ date ))->getTimestamp ();
183
+ $ date = $ this ->parseLocaleDate ($ date , $ locale , $ timezone , $ includeTime )
184
+ ?: (new \DateTime ($ date ))->getTimestamp ();
187
185
break ;
188
186
}
189
187
@@ -343,33 +341,77 @@ public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s')
343
341
private function appendTimeIfNeeded ($ date , $ includeTime , $ timezone , $ locale )
344
342
{
345
343
if ($ includeTime && !preg_match ('/\d{1}:\d{2}/ ' , $ date )) {
346
-
347
- $ formatterWithoutHour = new \IntlDateFormatter (
348
- $ locale ,
349
- \IntlDateFormatter::MEDIUM ,
350
- \IntlDateFormatter::NONE ,
351
- new \DateTimeZone ($ timezone )
352
- );
353
- $ convertedDate = $ formatterWithoutHour ->parse ($ date );
354
-
344
+ $ convertedDate = $ this ->parseLocaleDate ($ date , $ locale , $ timezone , false );
355
345
if (!$ convertedDate ) {
356
346
throw new LocalizedException (
357
347
new Phrase (
358
348
'Could not append time to DateTime '
359
349
)
360
350
);
361
-
362
351
}
363
352
364
- $ formatterWithHour = new \ IntlDateFormatter (
353
+ $ formatterWithHour = $ this -> getDateFormatter (
365
354
$ locale ,
355
+ $ timezone ,
366
356
\IntlDateFormatter::MEDIUM ,
367
- \IntlDateFormatter::SHORT ,
368
- new \DateTimeZone ($ timezone )
357
+ \IntlDateFormatter::SHORT
369
358
);
370
-
371
359
$ date = $ formatterWithHour ->format ($ convertedDate );
372
360
}
373
361
return $ date ;
374
362
}
363
+
364
+ /**
365
+ * Parse date by locale format through IntlDateFormatter
366
+ *
367
+ * @param string $date
368
+ * @param string $locale
369
+ * @param string $timeZone
370
+ * @param bool $includeTime
371
+ * @return int|null Timestamp of date
372
+ */
373
+ private function parseLocaleDate (string $ date , string $ locale , string $ timeZone , bool $ includeTime ): ?int
374
+ {
375
+ $ allowedStyles = [\IntlDateFormatter::MEDIUM , \IntlDateFormatter::SHORT ];
376
+ $ timeStyle = $ includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE ;
377
+
378
+ /**
379
+ * Try to parse date with different styles
380
+ */
381
+ foreach ($ allowedStyles as $ style ) {
382
+ $ formatter = $ this ->getDateFormatter ($ locale , $ timeZone , $ style , $ timeStyle );
383
+ $ timeStamp = $ formatter ->parse ($ date );
384
+ if ($ timeStamp ) {
385
+ return $ timeStamp ;
386
+ }
387
+ }
388
+
389
+ return null ;
390
+ }
391
+
392
+ /**
393
+ * Get date formatter for locale
394
+ *
395
+ * @param string $locale
396
+ * @param string $timeZone
397
+ * @param int $style
398
+ * @param int $timeStyle
399
+ * @return \IntlDateFormatter
400
+ */
401
+ private function getDateFormatter (string $ locale , string $ timeZone , int $ style , int $ timeStyle ): \IntlDateFormatter
402
+ {
403
+ $ cacheKey = "{$ locale }_ {$ timeZone }_ {$ style }_ {$ timeStyle }" ;
404
+ if (isset ($ this ->dateFormatterCache [$ cacheKey ])) {
405
+ return $ this ->dateFormatterCache [$ cacheKey ];
406
+ }
407
+
408
+ $ this ->dateFormatterCache [$ cacheKey ] = new \IntlDateFormatter (
409
+ $ locale ,
410
+ $ style ,
411
+ $ timeStyle ,
412
+ new \DateTimeZone ($ timeZone )
413
+ );
414
+
415
+ return $ this ->dateFormatterCache [$ cacheKey ];
416
+ }
375
417
}
0 commit comments