nfTlWNl rn Ѻq$³*L ZR]_-H#GDn,|2 ^C#֒Hnn!V5J4ot&:5_ӚHl {SgjK\՝Y z[)҇wk LHӨ}HEMkHNclYk;K`3 )1cK!qtkd"rڮ OLirbTWb&#& ~!M6$^Zmn't݆PDN 93<I\ 8F=Ϗ,ܞI|?`&߲Uөwr$),mnJN>Ԧ.V}OE;5tt҆cClzk׀D};ܩ~"!tzJPJ:uK z$VN}M!Lf1'VD_ȯ- ~wRz^(;RD7J(;^@sH$|K,{3 -M"ȫYԿvpi %T~"&BAȄg}YC~Y&tzJPJ:uK]sv\ zbrCr v'PGdo5-ng<%%fcs% TO6WHm"z}X"7-e q΁]v=t0KqEF;p)% 7%iŶN?PPMku3Rm l!`ɐC0 cSkz tIAM9Vd@VrpU-BXXI;"6NfёhWHݲ ٘q[mfSPޜ9P*ot+9!r'g<%%fIm#PӪa֤At]2<}$423 ř;nrubu?MQݰL]l!YB:y^m2gt%3-@e+a hd۫bP#&+)bs7JEOcvsY6T5z<_b2+GMpYbî,byFZ'1$({A6.q,G#0 %( mDvY1DO#)Ir(xْg0Ŋ &;:j ȵV5Sц,"n((,Y44j9W6ؾI2OEFx*PdMc ܡez'IU-`ֽ-&'c&j#wx\zxOqռJQ$)z +_-ѵ`=.yn)歨Mʳ q%AzꨊNxyt^`ђz-U􃪮$'2.%݆މĠmZ:uU \iC,Q]. JPX1y`գɹu< t%:Twnkl'HwLak6a$s/6:=z8³OQV#n[O-tzJPJ:uK9[ng)r.TÅl01d_m NmDͥB~ڲg<%%fSfH@\X5Uu3=>;ϸD I]P,ݭ\LC$}QI HlYt&ޥ&ĹB6U6Tv'ÝJџ<4t%q1fH:[ _p[)4Mڎ5S]=so.Z-Pq>o4ş)KOFw\ }Z 4\ݎ m^= +KUz0Q$ ([{9^1Ox˲7Em˜GdDT)!PDI4px I)"P wE[B9ˈ!@\b%2w7J-1](MH?b .}A8,@8G*<"bl5 trӮ{Fpmx9U }ʯ_ِuursl?&tak86yGwdˡ X=>I.QPsEM Gw'^mwiZ2?:c+|"joGK@`#v~|* lؘ(O!w:u/1+}r;dR:dRTu/\aQt!_ş/YbS<*UB(/p7W5PD=-7G7!J!yҨZ qmCpmKJN >αjx7u!F\ 0A.aI4 q)I]]D.^3J%ayf-չ_0&c17A] .Z`@ @zӵ~8[N! O~*:}^ gUVBc~W]\‰,R+|H-e{mOGV3Zb7hGG 'e_Mdb1{tnfg}jx'z{2Si#׉a䛿L )YW_բ_ztyO+6Ӥ61Y'c)H9Ebo(mX%H~1e>#x s#e芽K_e+羼nBSBr^M p-=or$f2`hn&^| v(VSMQnfp0gQaٳeΏVװUuWAvʊt̪VhR4d1Cx"+;*1;E!3`Mw$[ VmSekt88A~eU|쉄F[bkQ=&Uیy:&S۷Z7r!岲,+ f1J5l %k20^dMk:4.T*]X3{յ;ĴR"Ogq}iIa79Ĺy XNz&;P{>mF^qXMjyԾ)8zz b9?-nB4YjC%- R+?;#*Q7%.tZ]ag\Z|U),R0-^iS ?~K-.Ca.%4BįC >m!n mP=@OI$^LxMu{[9E4և`ǴZ<ޞH݋,ڥ4A!YۦSP I7nW o: DEP7G썚 ^-%mc UW, $format); // OpenOffice.org uses upper-case number formats, e.g. 'YYYY', convert to lower-case; // but we don't want to change any quoted strings /** @var callable */ $callable = [self::class, 'setLowercaseCallback']; $format = (string) preg_replace_callback('/(?:^|")([^"]*)(?:$|")/', $callable, $format); // Only process the non-quoted blocks for date format characters $blocks = explode('"', $format); foreach ($blocks as $key => &$block) { if ($key % 2 == 0) { $block = strtr($block, self::DATE_FORMAT_REPLACEMENTS); if (!strpos($block, 'A')) { // 24-hour time format // when [h]:mm format, the [h] should replace to the hours of the value * 24 $seekingBracket = true; self::tryInterval($seekingBracket, $block, $value, '[h]'); self::tryInterval($seekingBracket, $block, $value, '[hh]'); self::tryInterval($seekingBracket, $block, $value, '[mm]'); self::tryInterval($seekingBracket, $block, $value, '[m]'); self::tryInterval($seekingBracket, $block, $value, '[s]'); self::tryInterval($seekingBracket, $block, $value, '[ss]'); $block = strtr($block, self::DATE_FORMAT_REPLACEMENTS24); } else { // 12-hour time format $block = strtr($block, self::DATE_FORMAT_REPLACEMENTS12); } } } $format = implode('"', $blocks); // escape any quoted characters so that DateTime format() will render them correctly /** @var callable */ $callback = [self::class, 'escapeQuotesCallback']; $format = (string) preg_replace_callback('/"(.*)"/U', $callback, $format); $dateObj = Date::excelToDateTimeObject($value); // If the colon preceding minute had been quoted, as happens in // Excel 2003 XML formats, m will not have been changed to i above. // Change it now. $format = (string) \preg_replace('/\\\\:m/', ':i', $format); return $dateObj->format($format); } private static function setLowercaseCallback(array $matches): string { return mb_strtolower($matches[0]); } private static function escapeQuotesCallback(array $matches): string { return '\\' . implode('\\', /** @scrutinizer ignore-type */ str_split($matches[1])); } }