File indexing completed on 2024-12-22 05:36:50
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Locale 0017 * @subpackage Format 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @version $Id$ 0020 * @license http://framework.zend.com/license/new-bsd New BSD License 0021 */ 0022 0023 /** 0024 * include needed classes 0025 */ 0026 // require_once 'Zend/Locale/Data.php'; 0027 0028 /** 0029 * @category Zend 0030 * @package Zend_Locale 0031 * @subpackage Format 0032 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0033 * @license http://framework.zend.com/license/new-bsd New BSD License 0034 */ 0035 class Zend_Locale_Format 0036 { 0037 const STANDARD = 'auto'; 0038 0039 private static $_options = array('date_format' => null, 0040 'number_format' => null, 0041 'format_type' => 'iso', 0042 'fix_date' => false, 0043 'locale' => null, 0044 'cache' => null, 0045 'disableCache' => null, 0046 'precision' => null); 0047 0048 /** 0049 * Sets class wide options, if no option was given, the actual set options will be returned 0050 * The 'precision' option of a value is used to truncate or stretch extra digits. -1 means not to touch the extra digits. 0051 * The 'locale' option helps when parsing numbers and dates using separators and month names. 0052 * The date format 'format_type' option selects between CLDR/ISO date format specifier tokens and PHP's date() tokens. 0053 * The 'fix_date' option enables or disables heuristics that attempt to correct invalid dates. 0054 * The 'number_format' option can be used to specify a default number format string 0055 * The 'date_format' option can be used to specify a default date format string, but beware of using getDate(), 0056 * checkDateFormat() and getTime() after using setOptions() with a 'format'. To use these four methods 0057 * with the default date format for a locale, use array('date_format' => null, 'locale' => $locale) for their options. 0058 * 0059 * @param array $options Array of options, keyed by option name: format_type = 'iso' | 'php', fix_date = true | false, 0060 * locale = Zend_Locale | locale string, precision = whole number between -1 and 30 0061 * @throws Zend_Locale_Exception 0062 * @return array if no option was given 0063 */ 0064 public static function setOptions(array $options = array()) 0065 { 0066 self::$_options = self::_checkOptions($options) + self::$_options; 0067 return self::$_options; 0068 } 0069 0070 /** 0071 * Internal function for checking the options array of proper input values 0072 * See {@link setOptions()} for details. 0073 * 0074 * @param array $options Array of options, keyed by option name: format_type = 'iso' | 'php', fix_date = true | false, 0075 * locale = Zend_Locale | locale string, precision = whole number between -1 and 30 0076 * @throws Zend_Locale_Exception 0077 * @return array if no option was given 0078 */ 0079 private static function _checkOptions(array $options = array()) 0080 { 0081 if (count($options) == 0) { 0082 return self::$_options; 0083 } 0084 foreach ($options as $name => $value) { 0085 $name = strtolower($name); 0086 if ($name !== 'locale') { 0087 if (gettype($value) === 'string') { 0088 $value = strtolower($value); 0089 } 0090 } 0091 0092 switch($name) { 0093 case 'number_format' : 0094 if ($value == Zend_Locale_Format::STANDARD) { 0095 $locale = self::$_options['locale']; 0096 if (isset($options['locale'])) { 0097 $locale = $options['locale']; 0098 } 0099 $options['number_format'] = Zend_Locale_Data::getContent($locale, 'decimalnumber'); 0100 } else if ((gettype($value) !== 'string') and ($value !== NULL)) { 0101 // require_once 'Zend/Locale/Exception.php'; 0102 $stringValue = (string)(is_array($value) ? implode(' ', $value) : $value); 0103 throw new Zend_Locale_Exception("Unknown number format type '" . gettype($value) . "'. " 0104 . "Format '$stringValue' must be a valid number format string."); 0105 } 0106 break; 0107 0108 case 'date_format' : 0109 if ($value == Zend_Locale_Format::STANDARD) { 0110 $locale = self::$_options['locale']; 0111 if (isset($options['locale'])) { 0112 $locale = $options['locale']; 0113 } 0114 $options['date_format'] = Zend_Locale_Format::getDateFormat($locale); 0115 } else if ((gettype($value) !== 'string') and ($value !== NULL)) { 0116 // require_once 'Zend/Locale/Exception.php'; 0117 $stringValue = (string)(is_array($value) ? implode(' ', $value) : $value); 0118 throw new Zend_Locale_Exception("Unknown dateformat type '" . gettype($value) . "'. " 0119 . "Format '$stringValue' must be a valid ISO or PHP date format string."); 0120 } else { 0121 if (((isset($options['format_type']) === true) and ($options['format_type'] == 'php')) or 0122 ((isset($options['format_type']) === false) and (self::$_options['format_type'] == 'php'))) { 0123 $options['date_format'] = Zend_Locale_Format::convertPhpToIsoFormat($value); 0124 } 0125 } 0126 break; 0127 0128 case 'format_type' : 0129 if (($value != 'php') && ($value != 'iso')) { 0130 // require_once 'Zend/Locale/Exception.php'; 0131 throw new Zend_Locale_Exception("Unknown date format type '$value'. Only 'iso' and 'php'" 0132 . " are supported."); 0133 } 0134 break; 0135 0136 case 'fix_date' : 0137 if (($value !== true) && ($value !== false)) { 0138 // require_once 'Zend/Locale/Exception.php'; 0139 throw new Zend_Locale_Exception("Enabling correction of dates must be either true or false" 0140 . "(fix_date='$value')."); 0141 } 0142 break; 0143 0144 case 'locale' : 0145 $options['locale'] = Zend_Locale::findLocale($value); 0146 break; 0147 0148 case 'cache' : 0149 if ($value instanceof Zend_Cache_Core) { 0150 Zend_Locale_Data::setCache($value); 0151 } 0152 break; 0153 0154 case 'disablecache' : 0155 if (null !== $value) { 0156 Zend_Locale_Data::disableCache($value); 0157 } 0158 break; 0159 0160 case 'precision' : 0161 if ($value === NULL) { 0162 $value = -1; 0163 } 0164 0165 if (($value < -1) || ($value > 30)) { 0166 // require_once 'Zend/Locale/Exception.php'; 0167 throw new Zend_Locale_Exception("'$value' precision is not a whole number less than 30."); 0168 } 0169 break; 0170 0171 default: 0172 // require_once 'Zend/Locale/Exception.php'; 0173 throw new Zend_Locale_Exception("Unknown option: '$name' = '$value'"); 0174 break; 0175 0176 } 0177 } 0178 0179 return $options; 0180 } 0181 0182 /** 0183 * Changes the numbers/digits within a given string from one script to another 0184 * 'Decimal' representated the stardard numbers 0-9, if a script does not exist 0185 * an exception will be thrown. 0186 * 0187 * Examples for conversion from Arabic to Latin numerals: 0188 * convertNumerals('١١٠ Tests', 'Arab'); -> returns '100 Tests' 0189 * Example for conversion from Latin to Arabic numerals: 0190 * convertNumerals('100 Tests', 'Latn', 'Arab'); -> returns '١١٠ Tests' 0191 * 0192 * @param string $input String to convert 0193 * @param string $from Script to parse, see {@link Zend_Locale::getScriptList()} for details. 0194 * @param string $to OPTIONAL Script to convert to 0195 * @return string Returns the converted input 0196 * @throws Zend_Locale_Exception 0197 */ 0198 public static function convertNumerals($input, $from, $to = null) 0199 { 0200 if (!self::_getUniCodeSupport()) { 0201 trigger_error("Sorry, your PCRE extension does not support UTF8 which is needed for the I18N core", E_USER_NOTICE); 0202 } 0203 0204 $from = strtolower($from); 0205 $source = Zend_Locale_Data::getContent('en', 'numberingsystem', $from); 0206 if (empty($source)) { 0207 // require_once 'Zend/Locale/Exception.php'; 0208 throw new Zend_Locale_Exception("Unknown script '$from'. Use 'Latn' for digits 0,1,2,3,4,5,6,7,8,9."); 0209 } 0210 0211 if ($to !== null) { 0212 $to = strtolower($to); 0213 $target = Zend_Locale_Data::getContent('en', 'numberingsystem', $to); 0214 if (empty($target)) { 0215 // require_once 'Zend/Locale/Exception.php'; 0216 throw new Zend_Locale_Exception("Unknown script '$to'. Use 'Latn' for digits 0,1,2,3,4,5,6,7,8,9."); 0217 } 0218 } else { 0219 $target = '0123456789'; 0220 } 0221 0222 for ($x = 0; $x < 10; ++$x) { 0223 $asource[$x] = "/" . iconv_substr($source, $x, 1, 'UTF-8') . "/u"; 0224 $atarget[$x] = iconv_substr($target, $x, 1, 'UTF-8'); 0225 } 0226 0227 return preg_replace($asource, $atarget, $input); 0228 } 0229 0230 /** 0231 * Returns the normalized number from a localized one 0232 * Parsing depends on given locale (grouping and decimal) 0233 * 0234 * Examples for input: 0235 * '2345.4356,1234' = 23455456.1234 0236 * '+23,3452.123' = 233452.123 0237 * '12343 ' = 12343 0238 * '-9456' = -9456 0239 * '0' = 0 0240 * 0241 * @param string $input Input string to parse for numbers 0242 * @param array $options Options: locale, precision. See {@link setOptions()} for details. 0243 * @return string Returns the extracted number 0244 * @throws Zend_Locale_Exception 0245 */ 0246 public static function getNumber($input, array $options = array()) 0247 { 0248 $options = self::_checkOptions($options) + self::$_options; 0249 if (!is_string($input)) { 0250 return $input; 0251 } 0252 0253 if (!self::isNumber($input, $options)) { 0254 // require_once 'Zend/Locale/Exception.php'; 0255 throw new Zend_Locale_Exception('No localized value in ' . $input . ' found, or the given number does not match the localized format'); 0256 } 0257 0258 // Get correct signs for this locale 0259 $symbols = Zend_Locale_Data::getList($options['locale'],'symbols'); 0260 // Change locale input to be default number 0261 if (($input[0] == $symbols['minus']) && ('-' != $input[0])) { 0262 $input = '-' . substr($input, 1); 0263 } 0264 0265 $input = str_replace($symbols['group'],'', $input); 0266 if (strpos($input, $symbols['decimal']) !== false) { 0267 if ($symbols['decimal'] != '.') { 0268 $input = str_replace($symbols['decimal'], ".", $input); 0269 } 0270 0271 $pre = substr($input, strpos($input, '.') + 1); 0272 if ($options['precision'] === null) { 0273 $options['precision'] = strlen($pre); 0274 } 0275 0276 if (strlen($pre) >= $options['precision']) { 0277 $input = substr($input, 0, strlen($input) - strlen($pre) + $options['precision']); 0278 } 0279 0280 if (($options['precision'] == 0) && ($input[strlen($input) - 1] == '.')) { 0281 $input = substr($input, 0, -1); 0282 } 0283 } 0284 0285 return $input; 0286 } 0287 0288 /** 0289 * Returns a locale formatted number depending on the given options. 0290 * The seperation and fraction sign is used from the set locale. 0291 * ##0.# -> 12345.12345 -> 12345.12345 0292 * ##0.00 -> 12345.12345 -> 12345.12 0293 * ##,##0.00 -> 12345.12345 -> 12,345.12 0294 * 0295 * @param string $value Localized number string 0296 * @param array $options Options: number_format, locale, precision. See {@link setOptions()} for details. 0297 * @return string locale formatted number 0298 * @throws Zend_Locale_Exception 0299 */ 0300 public static function toNumber($value, array $options = array()) 0301 { 0302 // load class within method for speed 0303 // require_once 'Zend/Locale/Math.php'; 0304 0305 $value = Zend_Locale_Math::floatalize($value); 0306 $value = Zend_Locale_Math::normalize($value); 0307 $options = self::_checkOptions($options) + self::$_options; 0308 $options['locale'] = (string) $options['locale']; 0309 0310 // Get correct signs for this locale 0311 $symbols = Zend_Locale_Data::getList($options['locale'], 'symbols'); 0312 $oenc = self::_getEncoding(); 0313 self::_setEncoding('UTF-8'); 0314 0315 // Get format 0316 $format = $options['number_format']; 0317 if ($format === null) { 0318 $format = Zend_Locale_Data::getContent($options['locale'], 'decimalnumber'); 0319 $format = self::_seperateFormat($format, $value, $options['precision']); 0320 0321 if ($options['precision'] !== null) { 0322 $value = Zend_Locale_Math::normalize(Zend_Locale_Math::round($value, $options['precision'])); 0323 } 0324 } else { 0325 // seperate negative format pattern when available 0326 $format = self::_seperateFormat($format, $value, $options['precision']); 0327 if (strpos($format, '.')) { 0328 if (is_numeric($options['precision'])) { 0329 $value = Zend_Locale_Math::round($value, $options['precision']); 0330 } else { 0331 if (substr($format, iconv_strpos($format, '.') + 1, 3) == '###') { 0332 $options['precision'] = null; 0333 } else { 0334 $options['precision'] = iconv_strlen(iconv_substr($format, iconv_strpos($format, '.') + 1, 0335 iconv_strrpos($format, '0') - iconv_strpos($format, '.'))); 0336 $format = iconv_substr($format, 0, iconv_strpos($format, '.') + 1) . '###' 0337 . iconv_substr($format, iconv_strrpos($format, '0') + 1); 0338 } 0339 } 0340 } else { 0341 $value = Zend_Locale_Math::round($value, 0); 0342 $options['precision'] = 0; 0343 } 0344 $value = Zend_Locale_Math::normalize($value); 0345 } 0346 0347 if (iconv_strpos($format, '0') === false) { 0348 self::_setEncoding($oenc); 0349 // require_once 'Zend/Locale/Exception.php'; 0350 throw new Zend_Locale_Exception('Wrong format... missing 0'); 0351 } 0352 0353 // get number parts 0354 $pos = iconv_strpos($value, '.'); 0355 if ($pos !== false) { 0356 if ($options['precision'] === null) { 0357 $precstr = iconv_substr($value, $pos + 1); 0358 } else { 0359 $precstr = iconv_substr($value, $pos + 1, $options['precision']); 0360 if (iconv_strlen($precstr) < $options['precision']) { 0361 $precstr = $precstr . str_pad("0", ($options['precision'] - iconv_strlen($precstr)), "0"); 0362 } 0363 } 0364 } else { 0365 if ($options['precision'] > 0) { 0366 $precstr = str_pad("0", ($options['precision']), "0"); 0367 } 0368 } 0369 0370 if ($options['precision'] === null) { 0371 if (isset($precstr)) { 0372 $options['precision'] = iconv_strlen($precstr); 0373 } else { 0374 $options['precision'] = 0; 0375 } 0376 } 0377 0378 // get fraction and format lengths 0379 if (strpos($value, '.') !== false) { 0380 $number = substr((string) $value, 0, strpos($value, '.')); 0381 } else { 0382 $number = $value; 0383 } 0384 0385 $prec = call_user_func(Zend_Locale_Math::$sub, $value, $number, $options['precision']); 0386 $prec = Zend_Locale_Math::floatalize($prec); 0387 $prec = Zend_Locale_Math::normalize($prec); 0388 if (iconv_strpos($prec, '-') !== false) { 0389 $prec = iconv_substr($prec, 1); 0390 } 0391 0392 if (($prec == 0) and ($options['precision'] > 0)) { 0393 $prec = "0.0"; 0394 } 0395 0396 if (($options['precision'] + 2) > iconv_strlen($prec)) { 0397 $prec = str_pad((string) $prec, $options['precision'] + 2, "0", STR_PAD_RIGHT); 0398 } 0399 0400 if (iconv_strpos($number, '-') !== false) { 0401 $number = iconv_substr($number, 1); 0402 } 0403 $group = iconv_strrpos($format, ','); 0404 $group2 = iconv_strpos ($format, ','); 0405 $point = iconv_strpos ($format, '0'); 0406 // Add fraction 0407 $rest = ""; 0408 if (iconv_strpos($format, '.')) { 0409 $rest = iconv_substr($format, iconv_strpos($format, '.') + 1); 0410 $length = iconv_strlen($rest); 0411 for($x = 0; $x < $length; ++$x) { 0412 if (($rest[0] == '0') || ($rest[0] == '#')) { 0413 $rest = iconv_substr($rest, 1); 0414 } 0415 } 0416 $format = iconv_substr($format, 0, iconv_strlen($format) - iconv_strlen($rest)); 0417 } 0418 0419 if ($options['precision'] == '0') { 0420 if (iconv_strrpos($format, '-') != 0) { 0421 $format = iconv_substr($format, 0, $point) 0422 . iconv_substr($format, iconv_strrpos($format, '#') + 2); 0423 } else { 0424 $format = iconv_substr($format, 0, $point); 0425 } 0426 } else { 0427 $format = iconv_substr($format, 0, $point) . $symbols['decimal'] 0428 . iconv_substr($prec, 2); 0429 } 0430 0431 $format .= $rest; 0432 // Add seperation 0433 if ($group == 0) { 0434 // no seperation 0435 $format = $number . iconv_substr($format, $point); 0436 } else if ($group == $group2) { 0437 // only 1 seperation 0438 $seperation = ($point - $group); 0439 for ($x = iconv_strlen($number); $x > $seperation; $x -= $seperation) { 0440 if (iconv_substr($number, 0, $x - $seperation) !== "") { 0441 $number = iconv_substr($number, 0, $x - $seperation) . $symbols['group'] 0442 . iconv_substr($number, $x - $seperation); 0443 } 0444 } 0445 $format = iconv_substr($format, 0, iconv_strpos($format, '#')) . $number . iconv_substr($format, $point); 0446 } else { 0447 0448 // 2 seperations 0449 if (iconv_strlen($number) > ($point - $group)) { 0450 $seperation = ($point - $group); 0451 $number = iconv_substr($number, 0, iconv_strlen($number) - $seperation) . $symbols['group'] 0452 . iconv_substr($number, iconv_strlen($number) - $seperation); 0453 0454 if ((iconv_strlen($number) - 1) > ($point - $group + 1)) { 0455 $seperation2 = ($group - $group2 - 1); 0456 for ($x = iconv_strlen($number) - $seperation2 - 2; $x > $seperation2; $x -= $seperation2) { 0457 $number = iconv_substr($number, 0, $x - $seperation2) . $symbols['group'] 0458 . iconv_substr($number, $x - $seperation2); 0459 } 0460 } 0461 0462 } 0463 $format = iconv_substr($format, 0, iconv_strpos($format, '#')) . $number . iconv_substr($format, $point); 0464 } 0465 // set negative sign 0466 if (call_user_func(Zend_Locale_Math::$comp, $value, 0, $options['precision']) < 0) { 0467 if (iconv_strpos($format, '-') === false) { 0468 $format = $symbols['minus'] . $format; 0469 } else { 0470 $format = str_replace('-', $symbols['minus'], $format); 0471 } 0472 } 0473 0474 self::_setEncoding($oenc); 0475 return (string) $format; 0476 } 0477 0478 /** 0479 * @param string $format 0480 * @param string $value 0481 * @param int $precision 0482 * @return string 0483 */ 0484 private static function _seperateFormat($format, $value, $precision) 0485 { 0486 if (iconv_strpos($format, ';') !== false) { 0487 if (call_user_func(Zend_Locale_Math::$comp, $value, 0, $precision) < 0) { 0488 $tmpformat = iconv_substr($format, iconv_strpos($format, ';') + 1); 0489 if ($tmpformat[0] == '(') { 0490 $format = iconv_substr($format, 0, iconv_strpos($format, ';')); 0491 } else { 0492 $format = $tmpformat; 0493 } 0494 } else { 0495 $format = iconv_substr($format, 0, iconv_strpos($format, ';')); 0496 } 0497 } 0498 0499 return $format; 0500 } 0501 0502 0503 /** 0504 * Checks if the input contains a normalized or localized number 0505 * 0506 * @param string $input Localized number string 0507 * @param array $options Options: locale. See {@link setOptions()} for details. 0508 * @return boolean Returns true if a number was found 0509 */ 0510 public static function isNumber($input, array $options = array()) 0511 { 0512 if (!self::_getUniCodeSupport()) { 0513 trigger_error("Sorry, your PCRE extension does not support UTF8 which is needed for the I18N core", E_USER_NOTICE); 0514 } 0515 0516 $options = self::_checkOptions($options) + self::$_options; 0517 0518 // Get correct signs for this locale 0519 $symbols = Zend_Locale_Data::getList($options['locale'],'symbols'); 0520 0521 $regexs = Zend_Locale_Format::_getRegexForType('decimalnumber', $options); 0522 $regexs = array_merge($regexs, Zend_Locale_Format::_getRegexForType('scientificnumber', $options)); 0523 if (!empty($input) && ($input[0] == $symbols['decimal'])) { 0524 $input = 0 . $input; 0525 } 0526 foreach ($regexs as $regex) { 0527 preg_match($regex, $input, $found); 0528 if (isset($found[0])) { 0529 return true; 0530 } 0531 } 0532 0533 return false; 0534 } 0535 0536 /** 0537 * Internal method to convert cldr number syntax into regex 0538 * 0539 * @param string $type 0540 * @param array $options Options: locale. See {@link setOptions()} for details. 0541 * @return string 0542 * @throws Zend_Locale_Exception 0543 */ 0544 private static function _getRegexForType($type, $options) 0545 { 0546 $decimal = Zend_Locale_Data::getContent($options['locale'], $type); 0547 $decimal = preg_replace('/[^#0,;\.\-Ee]/u', '',$decimal); 0548 $patterns = explode(';', $decimal); 0549 0550 if (count($patterns) == 1) { 0551 $patterns[1] = '-' . $patterns[0]; 0552 } 0553 0554 $symbols = Zend_Locale_Data::getList($options['locale'],'symbols'); 0555 0556 foreach($patterns as $pkey => $pattern) { 0557 $regex[$pkey] = '/^'; 0558 $rest = 0; 0559 $end = null; 0560 if (strpos($pattern, '.') !== false) { 0561 $end = substr($pattern, strpos($pattern, '.') + 1); 0562 $pattern = substr($pattern, 0, -strlen($end) - 1); 0563 } 0564 0565 if (strpos($pattern, ',') !== false) { 0566 $parts = explode(',', $pattern); 0567 $count = count($parts); 0568 foreach($parts as $key => $part) { 0569 switch ($part) { 0570 case '#': 0571 case '-#': 0572 if ($part[0] == '-') { 0573 $regex[$pkey] .= '[' . $symbols['minus'] . '-]{0,1}'; 0574 } else { 0575 $regex[$pkey] .= '[' . $symbols['plus'] . '+]{0,1}'; 0576 } 0577 0578 if (($parts[$key + 1]) == '##0') { 0579 $regex[$pkey] .= '[0-9]{1,3}'; 0580 } else if (($parts[$key + 1]) == '##') { 0581 $regex[$pkey] .= '[0-9]{1,2}'; 0582 } else { 0583 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 1):"' . $pattern . '"'); 0584 } 0585 break; 0586 case '##': 0587 if ($parts[$key + 1] == '##0') { 0588 $regex[$pkey] .= '(\\' . $symbols['group'] . '{0,1}[0-9]{2})*'; 0589 } else { 0590 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 2):"' . $pattern . '"'); 0591 } 0592 break; 0593 case '##0': 0594 if ($parts[$key - 1] == '##') { 0595 $regex[$pkey] .= '[0-9]'; 0596 } else if (($parts[$key - 1] == '#') || ($parts[$key - 1] == '-#')) { 0597 $regex[$pkey] .= '(\\' . $symbols['group'] . '{0,1}[0-9]{3})*'; 0598 } else { 0599 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 3):"' . $pattern . '"'); 0600 } 0601 break; 0602 case '#0': 0603 if ($key == 0) { 0604 $regex[$pkey] .= '[0-9]*'; 0605 } else { 0606 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 4):"' . $pattern . '"'); 0607 } 0608 break; 0609 } 0610 } 0611 } 0612 0613 if (strpos($pattern, 'E') !== false) { 0614 if (($pattern == '#E0') || ($pattern == '#E00')) { 0615 $regex[$pkey] .= '[' . $symbols['plus']. '+]{0,1}[0-9]{1,}(\\' . $symbols['decimal'] . '[0-9]{1,})*[eE][' . $symbols['plus']. '+]{0,1}[0-9]{1,}'; 0616 } else if (($pattern == '-#E0') || ($pattern == '-#E00')) { 0617 $regex[$pkey] .= '[' . $symbols['minus']. '-]{0,1}[0-9]{1,}(\\' . $symbols['decimal'] . '[0-9]{1,})*[eE][' . $symbols['minus']. '-]{0,1}[0-9]{1,}'; 0618 } else { 0619 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 5):"' . $pattern . '"'); 0620 } 0621 } 0622 0623 if (!empty($end)) { 0624 if ($end == '###') { 0625 $regex[$pkey] .= '(\\' . $symbols['decimal'] . '{1}[0-9]{1,}){0,1}'; 0626 } else if ($end == '###-') { 0627 $regex[$pkey] .= '(\\' . $symbols['decimal'] . '{1}[0-9]{1,}){0,1}[' . $symbols['minus']. '-]'; 0628 } else { 0629 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 6):"' . $pattern . '"'); 0630 } 0631 } 0632 0633 $regex[$pkey] .= '$/u'; 0634 } 0635 0636 return $regex; 0637 } 0638 0639 /** 0640 * Alias for getNumber 0641 * 0642 * @param string $input Number to localize 0643 * @param array $options Options: locale, precision. See {@link setOptions()} for details. 0644 * @return float 0645 */ 0646 public static function getFloat($input, array $options = array()) 0647 { 0648 return floatval(self::getNumber($input, $options)); 0649 } 0650 0651 /** 0652 * Returns a locale formatted integer number 0653 * Alias for toNumber() 0654 * 0655 * @param string $value Number to normalize 0656 * @param array $options Options: locale, precision. See {@link setOptions()} for details. 0657 * @return string Locale formatted number 0658 */ 0659 public static function toFloat($value, array $options = array()) 0660 { 0661 $options['number_format'] = Zend_Locale_Format::STANDARD; 0662 return self::toNumber($value, $options); 0663 } 0664 0665 /** 0666 * Returns if a float was found 0667 * Alias for isNumber() 0668 * 0669 * @param string $value Localized number string 0670 * @param array $options Options: locale. See {@link setOptions()} for details. 0671 * @return boolean Returns true if a number was found 0672 */ 0673 public static function isFloat($value, array $options = array()) 0674 { 0675 return self::isNumber($value, $options); 0676 } 0677 0678 /** 0679 * Returns the first found integer from an string 0680 * Parsing depends on given locale (grouping and decimal) 0681 * 0682 * Examples for input: 0683 * ' 2345.4356,1234' = 23455456 0684 * '+23,3452.123' = 233452 0685 * ' 12343 ' = 12343 0686 * '-9456km' = -9456 0687 * '0' = 0 0688 * '(-){0,1}(\d+(\.){0,1})*(\,){0,1})\d+' 0689 * 0690 * @param string $input Input string to parse for numbers 0691 * @param array $options Options: locale. See {@link setOptions()} for details. 0692 * @return integer Returns the extracted number 0693 */ 0694 public static function getInteger($input, array $options = array()) 0695 { 0696 $options['precision'] = 0; 0697 return intval(self::getFloat($input, $options)); 0698 } 0699 0700 /** 0701 * Returns a localized number 0702 * 0703 * @param string $value Number to normalize 0704 * @param array $options Options: locale. See {@link setOptions()} for details. 0705 * @return string Locale formatted number 0706 */ 0707 public static function toInteger($value, array $options = array()) 0708 { 0709 $options['precision'] = 0; 0710 $options['number_format'] = Zend_Locale_Format::STANDARD; 0711 return self::toNumber($value, $options); 0712 } 0713 0714 /** 0715 * Returns if a integer was found 0716 * 0717 * @param string $value Localized number string 0718 * @param array $options Options: locale. See {@link setOptions()} for details. 0719 * @return boolean Returns true if a integer was found 0720 */ 0721 public static function isInteger($value, array $options = array()) 0722 { 0723 if (!self::isNumber($value, $options)) { 0724 return false; 0725 } 0726 0727 if (self::getInteger($value, $options) == self::getFloat($value, $options)) { 0728 return true; 0729 } 0730 0731 return false; 0732 } 0733 0734 /** 0735 * Converts a format string from PHP's date format to ISO format 0736 * Remember that Zend Date always returns localized string, so a month name which returns the english 0737 * month in php's date() will return the translated month name with this function... use 'en' as locale 0738 * if you are in need of the original english names 0739 * 0740 * The conversion has the following restrictions: 0741 * 'a', 'A' - Meridiem is not explicit upper/lowercase, you have to upper/lowercase the translated value yourself 0742 * 0743 * @param string $format Format string in PHP's date format 0744 * @return string Format string in ISO format 0745 */ 0746 public static function convertPhpToIsoFormat($format) 0747 { 0748 if ($format === null) { 0749 return null; 0750 } 0751 0752 $convert = array( 0753 'd' => 'dd' , 'D' => 'EE' , 'j' => 'd' , 'l' => 'EEEE', 0754 'N' => 'eee' , 'S' => 'SS' , 'w' => 'e' , 'z' => 'D' , 0755 'W' => 'ww' , 'F' => 'MMMM', 'm' => 'MM' , 'M' => 'MMM' , 0756 'n' => 'M' , 't' => 'ddd' , 'L' => 'l' , 'o' => 'YYYY', 0757 'Y' => 'yyyy', 'y' => 'yy' , 'a' => 'a' , 'A' => 'a' , 0758 'B' => 'B' , 'g' => 'h' , 'G' => 'H' , 'h' => 'hh' , 0759 'H' => 'HH' , 'i' => 'mm' , 's' => 'ss' , 'e' => 'zzzz', 0760 'I' => 'I' , 'O' => 'Z' , 'P' => 'ZZZZ', 'T' => 'z' , 0761 'Z' => 'X' , 'c' => 'yyyy-MM-ddTHH:mm:ssZZZZ', 'r' => 'r', 0762 'U' => 'U', 0763 ); 0764 $escaped = false; 0765 $inEscapedString = false; 0766 $converted = array(); 0767 foreach (str_split($format) as $char) { 0768 if (!$escaped && $char == '\\') { 0769 // Next char will be escaped: let's remember it 0770 $escaped = true; 0771 } elseif ($escaped) { 0772 if (!$inEscapedString) { 0773 // First escaped string: start the quoted chunk 0774 $converted[] = "'"; 0775 $inEscapedString = true; 0776 } 0777 // Since the previous char was a \ and we are in the quoted 0778 // chunk, let's simply add $char as it is 0779 $converted[] = $char; 0780 $escaped = false; 0781 } elseif ($char == "'") { 0782 // Single quotes need to be escaped like this 0783 $converted[] = "''"; 0784 } else { 0785 if ($inEscapedString) { 0786 // Close the single-quoted chunk 0787 $converted[] = "'"; 0788 $inEscapedString = false; 0789 } 0790 // Convert the unescaped char if needed 0791 if (isset($convert[$char])) { 0792 $converted[] = $convert[$char]; 0793 } else { 0794 $converted[] = $char; 0795 } 0796 } 0797 } 0798 0799 return implode($converted); 0800 } 0801 0802 /** 0803 * Parse date and split in named array fields 0804 * 0805 * @param string $date Date string to parse 0806 * @param array $options Options: format_type, fix_date, locale, date_format. See {@link setOptions()} for details. 0807 * @return array Possible array members: day, month, year, hour, minute, second, fixed, format 0808 * @throws Zend_Locale_Exception 0809 */ 0810 private static function _parseDate($date, $options) 0811 { 0812 if (!self::_getUniCodeSupport()) { 0813 trigger_error("Sorry, your PCRE extension does not support UTF8 which is needed for the I18N core", E_USER_NOTICE); 0814 } 0815 0816 $options = self::_checkOptions($options) + self::$_options; 0817 $test = array('h', 'H', 'm', 's', 'y', 'Y', 'M', 'd', 'D', 'E', 'S', 'l', 'B', 'I', 0818 'X', 'r', 'U', 'G', 'w', 'e', 'a', 'A', 'Z', 'z', 'v'); 0819 0820 $format = $options['date_format']; 0821 $number = $date; // working copy 0822 $result['date_format'] = $format; // save the format used to normalize $number (convenience) 0823 $result['locale'] = $options['locale']; // save the locale used to normalize $number (convenience) 0824 0825 $oenc = self::_getEncoding(); 0826 self::_setEncoding('UTF-8'); 0827 $day = iconv_strpos($format, 'd'); 0828 $month = iconv_strpos($format, 'M'); 0829 $year = iconv_strpos($format, 'y'); 0830 $hour = iconv_strpos($format, 'H'); 0831 $min = iconv_strpos($format, 'm'); 0832 $sec = iconv_strpos($format, 's'); 0833 $am = null; 0834 if ($hour === false) { 0835 $hour = iconv_strpos($format, 'h'); 0836 } 0837 if ($year === false) { 0838 $year = iconv_strpos($format, 'Y'); 0839 } 0840 if ($day === false) { 0841 $day = iconv_strpos($format, 'E'); 0842 if ($day === false) { 0843 $day = iconv_strpos($format, 'D'); 0844 } 0845 } 0846 0847 if ($day !== false) { 0848 $parse[$day] = 'd'; 0849 if (!empty($options['locale']) && ($options['locale'] !== 'root') && 0850 (!is_object($options['locale']) || ((string) $options['locale'] !== 'root'))) { 0851 // erase day string 0852 $daylist = Zend_Locale_Data::getList($options['locale'], 'day'); 0853 foreach($daylist as $key => $name) { 0854 if (iconv_strpos($number, $name) !== false) { 0855 $number = str_replace($name, "EEEE", $number); 0856 break; 0857 } 0858 } 0859 } 0860 } 0861 $position = false; 0862 0863 if ($month !== false) { 0864 $parse[$month] = 'M'; 0865 if (!empty($options['locale']) && ($options['locale'] !== 'root') && 0866 (!is_object($options['locale']) || ((string) $options['locale'] !== 'root'))) { 0867 // prepare to convert month name to their numeric equivalents, if requested, 0868 // and we have a $options['locale'] 0869 $position = self::_replaceMonth($number, Zend_Locale_Data::getList($options['locale'], 0870 'month')); 0871 if ($position === false) { 0872 $position = self::_replaceMonth($number, Zend_Locale_Data::getList($options['locale'], 0873 'month', array('gregorian', 'format', 'abbreviated'))); 0874 } 0875 } 0876 } 0877 if ($year !== false) { 0878 $parse[$year] = 'y'; 0879 } 0880 if ($hour !== false) { 0881 $parse[$hour] = 'H'; 0882 } 0883 if ($min !== false) { 0884 $parse[$min] = 'm'; 0885 } 0886 if ($sec !== false) { 0887 $parse[$sec] = 's'; 0888 } 0889 0890 if (empty($parse)) { 0891 self::_setEncoding($oenc); 0892 // require_once 'Zend/Locale/Exception.php'; 0893 throw new Zend_Locale_Exception("Unknown date format, neither date nor time in '" . $format . "' found"); 0894 } 0895 ksort($parse); 0896 0897 // get daytime 0898 if (iconv_strpos($format, 'a') !== false) { 0899 if (iconv_strpos(strtoupper($number), strtoupper(Zend_Locale_Data::getContent($options['locale'], 'am'))) !== false) { 0900 $am = true; 0901 } else if (iconv_strpos(strtoupper($number), strtoupper(Zend_Locale_Data::getContent($options['locale'], 'pm'))) !== false) { 0902 $am = false; 0903 } 0904 } 0905 0906 // split number parts 0907 $split = false; 0908 preg_match_all('/\d+/u', $number, $splitted); 0909 0910 if (count($splitted[0]) == 0) { 0911 self::_setEncoding($oenc); 0912 // require_once 'Zend/Locale/Exception.php'; 0913 throw new Zend_Locale_Exception("No date part in '$date' found."); 0914 } 0915 if (count($splitted[0]) == 1) { 0916 $split = 0; 0917 } 0918 $cnt = 0; 0919 foreach($parse as $key => $value) { 0920 0921 switch($value) { 0922 case 'd': 0923 if ($split === false) { 0924 if (count($splitted[0]) > $cnt) { 0925 $result['day'] = $splitted[0][$cnt]; 0926 } 0927 } else { 0928 $result['day'] = iconv_substr($splitted[0][0], $split, 2); 0929 $split += 2; 0930 } 0931 ++$cnt; 0932 break; 0933 case 'M': 0934 if ($split === false) { 0935 if (count($splitted[0]) > $cnt) { 0936 $result['month'] = $splitted[0][$cnt]; 0937 } 0938 } else { 0939 $result['month'] = iconv_substr($splitted[0][0], $split, 2); 0940 $split += 2; 0941 } 0942 ++$cnt; 0943 break; 0944 case 'y': 0945 $length = 2; 0946 if ((iconv_substr($format, $year, 4) == 'yyyy') 0947 || (iconv_substr($format, $year, 4) == 'YYYY')) { 0948 $length = 4; 0949 } 0950 0951 if ($split === false) { 0952 if (count($splitted[0]) > $cnt) { 0953 $result['year'] = $splitted[0][$cnt]; 0954 } 0955 } else { 0956 $result['year'] = iconv_substr($splitted[0][0], $split, $length); 0957 $split += $length; 0958 } 0959 0960 ++$cnt; 0961 break; 0962 case 'H': 0963 if ($split === false) { 0964 if (count($splitted[0]) > $cnt) { 0965 $result['hour'] = $splitted[0][$cnt]; 0966 } 0967 } else { 0968 $result['hour'] = iconv_substr($splitted[0][0], $split, 2); 0969 $split += 2; 0970 } 0971 ++$cnt; 0972 break; 0973 case 'm': 0974 if ($split === false) { 0975 if (count($splitted[0]) > $cnt) { 0976 $result['minute'] = $splitted[0][$cnt]; 0977 } 0978 } else { 0979 $result['minute'] = iconv_substr($splitted[0][0], $split, 2); 0980 $split += 2; 0981 } 0982 ++$cnt; 0983 break; 0984 case 's': 0985 if ($split === false) { 0986 if (count($splitted[0]) > $cnt) { 0987 $result['second'] = $splitted[0][$cnt]; 0988 } 0989 } else { 0990 $result['second'] = iconv_substr($splitted[0][0], $split, 2); 0991 $split += 2; 0992 } 0993 ++$cnt; 0994 break; 0995 } 0996 } 0997 0998 // AM/PM correction 0999 if ($hour !== false) { 1000 if (($am === true) and ($result['hour'] == 12)){ 1001 $result['hour'] = 0; 1002 } else if (($am === false) and ($result['hour'] != 12)) { 1003 $result['hour'] += 12; 1004 } 1005 } 1006 1007 if ($options['fix_date'] === true) { 1008 $result['fixed'] = 0; // nothing has been "fixed" by swapping date parts around (yet) 1009 } 1010 1011 if ($day !== false) { 1012 // fix false month 1013 if (isset($result['day']) and isset($result['month'])) { 1014 if (($position !== false) and ((iconv_strpos($date, $result['day']) === false) or 1015 (isset($result['year']) and (iconv_strpos($date, $result['year']) === false)))) { 1016 if ($options['fix_date'] !== true) { 1017 self::_setEncoding($oenc); 1018 // require_once 'Zend/Locale/Exception.php'; 1019 throw new Zend_Locale_Exception("Unable to parse date '$date' using '" . $format 1020 . "' (false month, $position, $month)"); 1021 } 1022 $temp = $result['day']; 1023 $result['day'] = $result['month']; 1024 $result['month'] = $temp; 1025 $result['fixed'] = 1; 1026 } 1027 } 1028 1029 // fix switched values d <> y 1030 if (isset($result['day']) and isset($result['year'])) { 1031 if ($result['day'] > 31) { 1032 if ($options['fix_date'] !== true) { 1033 self::_setEncoding($oenc); 1034 // require_once 'Zend/Locale/Exception.php'; 1035 throw new Zend_Locale_Exception("Unable to parse date '$date' using '" 1036 . $format . "' (d <> y)"); 1037 } 1038 $temp = $result['year']; 1039 $result['year'] = $result['day']; 1040 $result['day'] = $temp; 1041 $result['fixed'] = 2; 1042 } 1043 } 1044 1045 // fix switched values M <> y 1046 if (isset($result['month']) and isset($result['year'])) { 1047 if ($result['month'] > 31) { 1048 if ($options['fix_date'] !== true) { 1049 self::_setEncoding($oenc); 1050 // require_once 'Zend/Locale/Exception.php'; 1051 throw new Zend_Locale_Exception("Unable to parse date '$date' using '" 1052 . $format . "' (M <> y)"); 1053 } 1054 $temp = $result['year']; 1055 $result['year'] = $result['month']; 1056 $result['month'] = $temp; 1057 $result['fixed'] = 3; 1058 } 1059 } 1060 1061 // fix switched values M <> d 1062 if (isset($result['month']) and isset($result['day'])) { 1063 if ($result['month'] > 12) { 1064 if ($options['fix_date'] !== true || $result['month'] > 31) { 1065 self::_setEncoding($oenc); 1066 // require_once 'Zend/Locale/Exception.php'; 1067 throw new Zend_Locale_Exception("Unable to parse date '$date' using '" 1068 . $format . "' (M <> d)"); 1069 } 1070 $temp = $result['day']; 1071 $result['day'] = $result['month']; 1072 $result['month'] = $temp; 1073 $result['fixed'] = 4; 1074 } 1075 } 1076 } 1077 1078 if (isset($result['year'])) { 1079 if (((iconv_strlen($result['year']) == 2) && ($result['year'] < 10)) || 1080 (((iconv_strpos($format, 'yy') !== false) && (iconv_strpos($format, 'yyyy') === false)) || 1081 ((iconv_strpos($format, 'YY') !== false) && (iconv_strpos($format, 'YYYY') === false)))) { 1082 if (($result['year'] >= 0) && ($result['year'] < 100)) { 1083 if ($result['year'] < 70) { 1084 $result['year'] = (int) $result['year'] + 100; 1085 } 1086 1087 $result['year'] = (int) $result['year'] + 1900; 1088 } 1089 } 1090 } 1091 1092 self::_setEncoding($oenc); 1093 return $result; 1094 } 1095 1096 /** 1097 * Search $number for a month name found in $monthlist, and replace if found. 1098 * 1099 * @param string $number Date string (modified) 1100 * @param array $monthlist List of month names 1101 * 1102 * @return int|false Position of replaced string (false if nothing replaced) 1103 */ 1104 protected static function _replaceMonth(&$number, $monthlist) 1105 { 1106 // If $locale was invalid, $monthlist will default to a "root" identity 1107 // mapping for each month number from 1 to 12. 1108 // If no $locale was given, or $locale was invalid, do not use this identity mapping to normalize. 1109 // Otherwise, translate locale aware month names in $number to their numeric equivalents. 1110 $position = false; 1111 if ($monthlist && $monthlist[1] != 1) { 1112 foreach($monthlist as $key => $name) { 1113 if (($position = iconv_strpos($number, $name, 0, 'UTF-8')) !== false) { 1114 $number = str_ireplace($name, $key, $number); 1115 return $position; 1116 } 1117 } 1118 } 1119 1120 return false; 1121 } 1122 1123 /** 1124 * Returns the default date format for $locale. 1125 * 1126 * @param string|Zend_Locale $locale OPTIONAL Locale of $number, possibly in string form (e.g. 'de_AT') 1127 * @return string format 1128 * @throws Zend_Locale_Exception throws an exception when locale data is broken 1129 */ 1130 public static function getDateFormat($locale = null) 1131 { 1132 $format = Zend_Locale_Data::getContent($locale, 'date'); 1133 if (empty($format)) { 1134 // require_once 'Zend/Locale/Exception.php'; 1135 throw new Zend_Locale_Exception("failed to receive data from locale $locale"); 1136 } 1137 1138 return $format; 1139 } 1140 1141 /** 1142 * Returns an array with the normalized date from an locale date 1143 * a input of 10.01.2006 without a $locale would return: 1144 * array ('day' => 10, 'month' => 1, 'year' => 2006) 1145 * The 'locale' option is only used to convert human readable day 1146 * and month names to their numeric equivalents. 1147 * The 'format' option allows specification of self-defined date formats, 1148 * when not using the default format for the 'locale'. 1149 * 1150 * @param string $date Date string 1151 * @param array $options Options: format_type, fix_date, locale, date_format. See {@link setOptions()} for details. 1152 * @return array Possible array members: day, month, year, hour, minute, second, fixed, format 1153 */ 1154 public static function getDate($date, array $options = array()) 1155 { 1156 $options = self::_checkOptions($options) + self::$_options; 1157 if (empty($options['date_format'])) { 1158 $options['format_type'] = 'iso'; 1159 $options['date_format'] = self::getDateFormat($options['locale']); 1160 } 1161 1162 return self::_parseDate($date, $options); 1163 } 1164 1165 /** 1166 * Returns if the given datestring contains all date parts from the given format. 1167 * If no format is given, the default date format from the locale is used 1168 * If you want to check if the date is a proper date you should use Zend_Date::isDate() 1169 * 1170 * @param string $date Date string 1171 * @param array $options Options: format_type, fix_date, locale, date_format. See {@link setOptions()} for details. 1172 * @return boolean 1173 */ 1174 public static function checkDateFormat($date, array $options = array()) 1175 { 1176 try { 1177 $date = self::getDate($date, $options); 1178 } catch (Exception $e) { 1179 return false; 1180 } 1181 1182 if (empty($options['date_format'])) { 1183 $options['format_type'] = 'iso'; 1184 $options['date_format'] = self::getDateFormat(isset($options['locale']) ? $options['locale'] : null); 1185 } 1186 $options = self::_checkOptions($options) + self::$_options; 1187 1188 // day expected but not parsed 1189 if ((iconv_strpos($options['date_format'], 'd', 0, 'UTF-8') !== false) and (!isset($date['day']) or ($date['day'] === ""))) { 1190 return false; 1191 } 1192 1193 // month expected but not parsed 1194 if ((iconv_strpos($options['date_format'], 'M', 0, 'UTF-8') !== false) and (!isset($date['month']) or ($date['month'] === ""))) { 1195 return false; 1196 } 1197 1198 // year expected but not parsed 1199 if (((iconv_strpos($options['date_format'], 'Y', 0, 'UTF-8') !== false) or 1200 (iconv_strpos($options['date_format'], 'y', 0, 'UTF-8') !== false)) and (!isset($date['year']) or ($date['year'] === ""))) { 1201 return false; 1202 } 1203 1204 // second expected but not parsed 1205 if ((iconv_strpos($options['date_format'], 's', 0, 'UTF-8') !== false) and (!isset($date['second']) or ($date['second'] === ""))) { 1206 return false; 1207 } 1208 1209 // minute expected but not parsed 1210 if ((iconv_strpos($options['date_format'], 'm', 0, 'UTF-8') !== false) and (!isset($date['minute']) or ($date['minute'] === ""))) { 1211 return false; 1212 } 1213 1214 // hour expected but not parsed 1215 if (((iconv_strpos($options['date_format'], 'H', 0, 'UTF-8') !== false) or 1216 (iconv_strpos($options['date_format'], 'h', 0, 'UTF-8') !== false)) and (!isset($date['hour']) or ($date['hour'] === ""))) { 1217 return false; 1218 } 1219 1220 return true; 1221 } 1222 1223 /** 1224 * Returns the default time format for $locale. 1225 * 1226 * @param string|Zend_Locale $locale OPTIONAL Locale of $number, possibly in string form (e.g. 'de_AT') 1227 * @return string format 1228 * @throws Zend_Locale_Exception 1229 */ 1230 public static function getTimeFormat($locale = null) 1231 { 1232 $format = Zend_Locale_Data::getContent($locale, 'time'); 1233 if (empty($format)) { 1234 // require_once 'Zend/Locale/Exception.php'; 1235 throw new Zend_Locale_Exception("failed to receive data from locale $locale"); 1236 } 1237 return $format; 1238 } 1239 1240 /** 1241 * Returns an array with 'hour', 'minute', and 'second' elements extracted from $time 1242 * according to the order described in $format. For a format of 'H:i:s', and 1243 * an input of 11:20:55, getTime() would return: 1244 * array ('hour' => 11, 'minute' => 20, 'second' => 55) 1245 * The optional $locale parameter may be used to help extract times from strings 1246 * containing both a time and a day or month name. 1247 * 1248 * @param string $time Time string 1249 * @param array $options Options: format_type, fix_date, locale, date_format. See {@link setOptions()} for details. 1250 * @return array Possible array members: day, month, year, hour, minute, second, fixed, format 1251 */ 1252 public static function getTime($time, array $options = array()) 1253 { 1254 $options = self::_checkOptions($options) + self::$_options; 1255 if (empty($options['date_format'])) { 1256 $options['format_type'] = 'iso'; 1257 $options['date_format'] = self::getTimeFormat($options['locale']); 1258 } 1259 return self::_parseDate($time, $options); 1260 } 1261 1262 /** 1263 * Returns the default datetime format for $locale. 1264 * 1265 * @param string|Zend_Locale $locale OPTIONAL Locale of $number, possibly in string form (e.g. 'de_AT') 1266 * @return string format 1267 * @throws Zend_Locale_Exception 1268 */ 1269 public static function getDateTimeFormat($locale = null) 1270 { 1271 $format = Zend_Locale_Data::getContent($locale, 'datetime'); 1272 if (empty($format)) { 1273 // require_once 'Zend/Locale/Exception.php'; 1274 throw new Zend_Locale_Exception("failed to receive data from locale $locale"); 1275 } 1276 return $format; 1277 } 1278 1279 /** 1280 * Returns an array with 'year', 'month', 'day', 'hour', 'minute', and 'second' elements 1281 * extracted from $datetime according to the order described in $format. For a format of 'd.M.y H:i:s', 1282 * and an input of 10.05.1985 11:20:55, getDateTime() would return: 1283 * array ('year' => 1985, 'month' => 5, 'day' => 10, 'hour' => 11, 'minute' => 20, 'second' => 55) 1284 * The optional $locale parameter may be used to help extract times from strings 1285 * containing both a time and a day or month name. 1286 * 1287 * @param string $datetime DateTime string 1288 * @param array $options Options: format_type, fix_date, locale, date_format. See {@link setOptions()} for details. 1289 * @return array Possible array members: day, month, year, hour, minute, second, fixed, format 1290 */ 1291 public static function getDateTime($datetime, array $options = array()) 1292 { 1293 $options = self::_checkOptions($options) + self::$_options; 1294 if (empty($options['date_format'])) { 1295 $options['format_type'] = 'iso'; 1296 $options['date_format'] = self::getDateTimeFormat($options['locale']); 1297 } 1298 return self::_parseDate($datetime, $options); 1299 } 1300 1301 /** 1302 * Internal method to detect of Unicode supports UTF8 1303 * which should be enabled within vanilla php installations 1304 * 1305 * @return boolean 1306 */ 1307 protected static function _getUniCodeSupport() 1308 { 1309 return (@preg_match('/\pL/u', 'a')) ? true : false; 1310 } 1311 1312 /** 1313 * Internal method to retrieve the current encoding via the ini setting 1314 * default_charset for PHP >= 5.6 or iconv_get_encoding otherwise. 1315 * 1316 * @return string 1317 */ 1318 protected static function _getEncoding() 1319 { 1320 $oenc = PHP_VERSION_ID < 50600 1321 ? iconv_get_encoding('internal_encoding') 1322 : ini_get('default_charset'); 1323 1324 return $oenc; 1325 } 1326 1327 /** 1328 * Internal method to set the encoding via the ini setting 1329 * default_charset for PHP >= 5.6 or iconv_set_encoding otherwise. 1330 * 1331 * @param string $encoding 1332 * @return void 1333 */ 1334 protected static function _setEncoding($encoding) 1335 { 1336 if (PHP_VERSION_ID < 50600) { 1337 iconv_set_encoding('internal_encoding', $encoding); 1338 } else { 1339 ini_set('default_charset', $encoding); 1340 } 1341 } 1342 }