1010
1111/**
1212 * Timezone library
13+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1314 */
1415class 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