10
10
11
11
/**
12
12
* Timezone library
13
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
13
14
*/
14
15
class Timezone implements TimezoneInterface
15
16
{
@@ -110,11 +111,21 @@ public function getConfigTimezone($scopeType = null, $scopeCode = null)
110
111
*/
111
112
public function getDateFormat ($ type = \IntlDateFormatter::SHORT )
112
113
{
113
- return (new \IntlDateFormatter (
114
+ $ pattern = (new \IntlDateFormatter (
114
115
$ this ->_localeResolver ->getLocale (),
115
116
$ type ,
116
117
\IntlDateFormatter::NONE
117
118
))->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 ;
118
129
}
119
130
120
131
/**
@@ -151,9 +162,8 @@ public function getDateTimeFormat($type)
151
162
152
163
/**
153
164
* {@inheritdoc}
154
- * @SuppressWarnings(PHPMD.NPathComplexity)
155
165
*/
156
- public function date ($ date = null , $ locale = null , $ useTimezone = true )
166
+ public function date ($ date = null , $ locale = null , $ useTimezone = true , $ includeTime = true )
157
167
{
158
168
$ locale = $ locale ?: $ this ->_localeResolver ->getLocale ();
159
169
$ timezone = $ useTimezone
@@ -164,17 +174,52 @@ public function date($date = null, $locale = null, $useTimezone = true)
164
174
return new \DateTime ('now ' , new \DateTimeZone ($ timezone ));
165
175
} elseif ($ date instanceof \DateTime) {
166
176
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 ());
167
179
} elseif (!is_numeric ($ date )) {
168
- $ formatter = new \IntlDateFormatter (
169
- $ locale ,
170
- \IntlDateFormatter::SHORT ,
171
- \IntlDateFormatter::NONE
172
- );
173
- $ date = $ formatter ->parse ($ date ) ?: (new \DateTime ($ date ))->getTimestamp ();
180
+ $ date = $ this ->prepareDate ($ date , $ locale , $ timezone , $ includeTime );
174
181
}
182
+
175
183
return (new \DateTime (null , new \DateTimeZone ($ timezone )))->setTimestamp ($ date );
176
184
}
177
185
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 ($ date , $ locale , $ timezone , $ includeTime )
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
+
178
223
/**
179
224
* {@inheritdoc}
180
225
*/
@@ -195,7 +240,7 @@ public function formatDate($date = null, $format = \IntlDateFormatter::SHORT, $s
195
240
{
196
241
$ formatTime = $ showTime ? $ format : \IntlDateFormatter::NONE ;
197
242
198
- if (!($ date instanceof \DateTime )) {
243
+ if (!($ date instanceof \DateTimeInterface )) {
199
244
$ date = new \DateTime ($ date );
200
245
}
201
246
@@ -232,12 +277,8 @@ public function isScopeDateInInterval($scope, $dateFrom = null, $dateTo = null)
232
277
$ toTimeStamp += 86400 ;
233
278
}
234
279
235
- $ result = false ;
236
- if (!$ this ->_dateTime ->isEmptyDate ($ dateFrom ) && $ scopeTimeStamp < $ fromTimeStamp ) {
237
- } elseif (!$ this ->_dateTime ->isEmptyDate ($ dateTo ) && $ scopeTimeStamp > $ toTimeStamp ) {
238
- } else {
239
- $ result = true ;
240
- }
280
+ $ result = !(!$ this ->_dateTime ->isEmptyDate ($ dateFrom ) && $ scopeTimeStamp < $ fromTimeStamp )
281
+ && !(!$ this ->_dateTime ->isEmptyDate ($ dateTo ) && $ scopeTimeStamp > $ toTimeStamp );
241
282
return $ result ;
242
283
}
243
284
@@ -258,7 +299,7 @@ public function formatDateTime(
258
299
$ timezone = null ,
259
300
$ pattern = null
260
301
) {
261
- if (!($ date instanceof \DateTime )) {
302
+ if (!($ date instanceof \DateTimeInterface )) {
262
303
$ date = new \DateTime ($ date );
263
304
}
264
305
@@ -294,8 +335,12 @@ public function formatDateTime(
294
335
*/
295
336
public function convertConfigTimeToUtc ($ date , $ format = 'Y-m-d H:i:s ' )
296
337
{
297
- if (!($ date instanceof \DateTime)) {
298
- $ 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
+ }
299
344
} else {
300
345
if ($ date ->getTimezone ()->getName () !== $ this ->getConfigTimezone ()) {
301
346
throw new LocalizedException (
@@ -308,4 +353,18 @@ public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s')
308
353
309
354
return $ date ->format ($ format );
310
355
}
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 ($ date )
364
+ {
365
+ if (!preg_match ('/\d{1,2}:\d{2}/ ' , $ date )) {
366
+ $ date .= " 00:00 " ;
367
+ }
368
+ return $ date ;
369
+ }
311
370
}
0 commit comments