• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List

E:/E/GEAMP/www/openbiz/openbiz/others/Zend/Locale/Format.php

00001 <?php
00026 require_once 'Zend/Locale/Data.php';
00027 
00035 class Zend_Locale_Format
00036 {
00037     const STANDARD   = 'auto';
00038 
00039     private static $_options = array('date_format'   => null,
00040                                      'number_format' => null,
00041                                      'format_type'   => 'iso',
00042                                      'fix_date'      => false,
00043                                      'locale'        => null,
00044                                      'cache'         => null,
00045                                      'disableCache'  => false,
00046                                      'precision'     => null);
00047 
00064     public static function setOptions(array $options = array())
00065     {
00066         self::$_options = self::_checkOptions($options) + self::$_options;
00067         return self::$_options;
00068     }
00069 
00079     private static function _checkOptions(array $options = array())
00080     {
00081         if (count($options) == 0) {
00082             return self::$_options;
00083         }
00084         foreach ($options as $name => $value) {
00085             $name  = strtolower($name);
00086             if ($name !== 'locale') {
00087                 if (gettype($value) === 'string') {
00088                     $value = strtolower($value);
00089                 }
00090             }
00091 
00092             switch($name) {
00093                 case 'number_format' :
00094                     if ($value == Zend_Locale_Format::STANDARD) {
00095                         $locale = self::$_options['locale'];
00096                         if (isset($options['locale'])) {
00097                             $locale = $options['locale'];
00098                         }
00099                         $options['number_format'] = Zend_Locale_Data::getContent($locale, 'decimalnumber');
00100                     } else if ((gettype($value) !== 'string') and ($value !== NULL)) {
00101                         require_once 'Zend/Locale/Exception.php';
00102                         throw new Zend_Locale_Exception("Unknown number format type '" . gettype($value) . "'. "
00103                             . "Format '$value' must be a valid number format string.");
00104                     }
00105                     break;
00106 
00107                 case 'date_format' :
00108                     if ($value == Zend_Locale_Format::STANDARD) {
00109                         $locale = self::$_options['locale'];
00110                         if (isset($options['locale'])) {
00111                             $locale = $options['locale'];
00112                         }
00113                         $options['date_format'] = Zend_Locale_Format::getDateFormat($locale);
00114                     } else if ((gettype($value) !== 'string') and ($value !== NULL)) {
00115                         require_once 'Zend/Locale/Exception.php';
00116                         throw new Zend_Locale_Exception("Unknown dateformat type '" . gettype($value) . "'. "
00117                             . "Format '$value' must be a valid ISO or PHP date format string.");
00118                     } else {
00119                         if (((isset($options['format_type']) === true) and ($options['format_type'] == 'php')) or
00120                             ((isset($options['format_type']) === false) and (self::$_options['format_type'] == 'php'))) {
00121                             $options['date_format'] = Zend_Locale_Format::convertPhpToIsoFormat($value);
00122                         }
00123                     }
00124                     break;
00125 
00126                 case 'format_type' :
00127                     if (($value != 'php') && ($value != 'iso')) {
00128                         require_once 'Zend/Locale/Exception.php';
00129                         throw new Zend_Locale_Exception("Unknown date format type '$value'. Only 'iso' and 'php'"
00130                            . " are supported.");
00131                     }
00132                     break;
00133 
00134                 case 'fix_date' :
00135                     if (($value !== true) && ($value !== false)) {
00136                         require_once 'Zend/Locale/Exception.php';
00137                         throw new Zend_Locale_Exception("Enabling correction of dates must be either true or false"
00138                             . "(fix_date='$value').");
00139                     }
00140                     break;
00141 
00142                 case 'locale' :
00143                     $options['locale'] = Zend_Locale::findLocale($value);
00144                     break;
00145 
00146                 case 'cache' :
00147                     if ($value instanceof Zend_Cache_Core) {
00148                         Zend_Locale_Data::setCache($value);
00149                     }
00150                     break;
00151 
00152                 case 'disablecache' :
00153                     Zend_Locale_Data::disableCache($value);
00154                     break;
00155 
00156                 case 'precision' :
00157                     if ($value === NULL) {
00158                         $value = -1;
00159                     }
00160 
00161                     if (($value < -1) || ($value > 30)) {
00162                         require_once 'Zend/Locale/Exception.php';
00163                         throw new Zend_Locale_Exception("'$value' precision is not a whole number less than 30.");
00164                     }
00165                     break;
00166 
00167                 default:
00168                     require_once 'Zend/Locale/Exception.php';
00169                     throw new Zend_Locale_Exception("Unknown option: '$name' = '$value'");
00170                     break;
00171 
00172             }
00173         }
00174 
00175         return $options;
00176     }
00177 
00194     public static function convertNumerals($input, $from, $to = null)
00195     {
00196         $from   = strtolower($from);
00197         $source = Zend_Locale_Data::getContent('en', 'numberingsystem', $from);
00198         if (empty($source)) {
00199             require_once 'Zend/Locale/Exception.php';
00200             throw new Zend_Locale_Exception("Unknown script '$from'. Use 'Latn' for digits 0,1,2,3,4,5,6,7,8,9.");
00201         }
00202 
00203         if ($to !== null) {
00204             $to     = strtolower($to);
00205             $target = Zend_Locale_Data::getContent('en', 'numberingsystem', $to);
00206             if (empty($target)) {
00207                 require_once 'Zend/Locale/Exception.php';
00208                 throw new Zend_Locale_Exception("Unknown script '$to'. Use 'Latn' for digits 0,1,2,3,4,5,6,7,8,9.");
00209             }
00210         } else {
00211             $target = '0123456789';
00212         }
00213 
00214         for ($x = 0; $x < 10; ++$x) {
00215             $asource[$x] = "/" . iconv_substr($source, $x, 1) . "/u";
00216             $atarget[$x] = iconv_substr($target, $x, 1);
00217         }
00218 
00219         return preg_replace($asource, $atarget, $input);
00220     }
00221 
00238     public static function getNumber($input, array $options = array())
00239     {
00240         $options = self::_checkOptions($options) + self::$_options;
00241         if (!is_string($input)) {
00242             return $input;
00243         }
00244 
00245         if (!self::isNumber($input, $options)) {
00246             require_once 'Zend/Locale/Exception.php';
00247             throw new Zend_Locale_Exception('No localized value in ' . $input . ' found, or the given number does not match the localized format');
00248         }
00249 
00250         // Get correct signs for this locale
00251         $symbols = Zend_Locale_Data::getList($options['locale'],'symbols');
00252         // Change locale input to be default number
00253         if ((strpos($input, $symbols['minus']) !== false) ||
00254             (strpos($input, '-') !== false)) {
00255             $input = strtr($input, array($symbols['minus'] => '', '-' => ''));
00256             $input = '-' . $input;
00257         }
00258 
00259         $input = str_replace($symbols['group'],'', $input);
00260         if (strpos($input, $symbols['decimal']) !== false) {
00261             if ($symbols['decimal'] != '.') {
00262                 $input = str_replace($symbols['decimal'], ".", $input);
00263             }
00264 
00265             $pre = substr($input, strpos($input, '.') + 1);
00266             if ($options['precision'] === null) {
00267                 $options['precision'] = strlen($pre);
00268             }
00269 
00270             if (strlen($pre) >= $options['precision']) {
00271                 $input = substr($input, 0, strlen($input) - strlen($pre) + $options['precision']);
00272             }
00273         }
00274 
00275         return $input;
00276     }
00277 
00290     public static function toNumber($value, array $options = array())
00291     {
00292         // load class within method for speed
00293         require_once 'Zend/Locale/Math.php';
00294 
00295         $value             = Zend_Locale_Math::normalize($value);
00296         $value             = self::_floatalize($value);
00297         $options           = self::_checkOptions($options) + self::$_options;
00298         $options['locale'] = (string) $options['locale'];
00299 
00300         // Get correct signs for this locale
00301         $symbols = Zend_Locale_Data::getList($options['locale'], 'symbols');
00302         iconv_set_encoding('internal_encoding', 'UTF-8');
00303 
00304         // Get format
00305         $format = $options['number_format'];
00306         if ($format === null) {
00307             $format  = Zend_Locale_Data::getContent($options['locale'], 'decimalnumber');
00308             if (iconv_strpos($format, ';') !== false) {
00309                 if (call_user_func(Zend_Locale_Math::$comp, $value, 0, $options['precision']) < 0) {
00310                     $tmpformat = iconv_substr($format, iconv_strpos($format, ';') + 1);
00311                     if ($tmpformat[0] == '(') {
00312                         $format = iconv_substr($format, 0, iconv_strpos($format, ';'));
00313                     } else {
00314                         $format = $tmpformat;
00315                     }
00316                 } else {
00317                     $format = iconv_substr($format, 0, iconv_strpos($format, ';'));
00318                 }
00319             }
00320         } else {
00321             // seperate negative format pattern when available
00322             // @todo: The below conditional is a repeat of logic in the
00323             // previous conditional; it should be refactored to a protected
00324             // method to prevent code duplication.
00325             if (iconv_strpos($format, ';') !== false) {
00326                 if (call_user_func(Zend_Locale_Math::$comp, $value, 0, $options['precision']) < 0) {
00327                     $tmpformat = iconv_substr($format, iconv_strpos($format, ';') + 1);
00328                     if ($tmpformat[0] == '(') {
00329                         $format = iconv_substr($format, 0, iconv_strpos($format, ';'));
00330                     } else {
00331                         $format = $tmpformat;
00332                     }
00333                 } else {
00334                     $format = iconv_substr($format, 0, iconv_strpos($format, ';'));
00335                 }
00336             }
00337 
00338             if (strpos($format, '.')) {
00339                 if (is_numeric($options['precision'])) {
00340                     $value = Zend_Locale_Math::round($value, $options['precision']);
00341                     // Need to "floatalize" the number; when precision > 4
00342                     // and bcmath disabled, round() returns scientific notation
00343                     $value = self::_floatalize($value);
00344                 } else {
00345                     if (substr($format, iconv_strpos($format, '.') + 1, 3) == '###') {
00346                         $options['precision'] = null;
00347                     } else {
00348                         $options['precision'] = iconv_strlen(iconv_substr($format, iconv_strpos($format, '.') + 1,
00349                                                               iconv_strrpos($format, '0') - iconv_strpos($format, '.')));
00350                         $format = iconv_substr($format, 0, iconv_strpos($format, '.') + 1) . '###'
00351                                 . iconv_substr($format, iconv_strrpos($format, '0') + 1);
00352                     }
00353                 }
00354             } else {
00355                 $value = Zend_Locale_Math::round($value, 0);
00356                 // Need to "floatalize" the number; when precision > 4
00357                 // and bcmath disabled, round() returns scientific notation
00358                 $value = self::_floatalize($value);
00359                 $options['precision'] = 0;
00360             }
00361             $value = Zend_Locale_Math::normalize($value);
00362         }
00363 
00364         if (iconv_strpos($format, '0') === false) {
00365             require_once 'Zend/Locale/Exception.php';
00366             throw new Zend_Locale_Exception('Wrong format... missing 0');
00367         }
00368 
00369         // get number parts
00370         $pos = iconv_strpos($value, '.');
00371         if ($pos !== false) {
00372             if ($options['precision'] === null) {
00373                 $precstr = iconv_substr($value, $pos + 1);
00374             } else {
00375                 $precstr = iconv_substr($value, $pos + 1, $options['precision']);
00376                 if (iconv_strlen($precstr) < $options['precision']) {
00377                     $precstr = $precstr . str_pad("0", ($options['precision'] - iconv_strlen($precstr)), "0");
00378                 }
00379             }
00380         } else {
00381             if ($options['precision'] > 0) {
00382                 $precstr = str_pad("0", ($options['precision']), "0");
00383             }
00384         }
00385 
00386         if ($options['precision'] === null) {
00387             if (isset($precstr)) {
00388                 $options['precision'] = iconv_strlen($precstr);
00389             } else {
00390                 $options['precision'] = 0;
00391             }
00392         }
00393 
00394         // get fraction and format lengths
00395         if (strpos($value, '.') !== false) {
00396             $number = substr((string) $value, 0, strpos($value, '.'));
00397         } else {
00398             $number = $value;
00399         }
00400 
00401         $prec = call_user_func(Zend_Locale_Math::$sub, $value, $number, $options['precision']);
00402         $prec = Zend_Locale_Math::normalize($prec);
00403         if (iconv_strpos($prec, '-') !== false) {
00404             $prec = iconv_substr($prec, 1);
00405         }
00406 
00407         if (($prec == 0) and ($options['precision'] > 0)) {
00408             $prec = "0.0";
00409         }
00410 
00411         if (($options['precision'] + 2) > iconv_strlen($prec)) {
00412             $prec = str_pad((string) $prec, $options['precision'] + 2, "0", STR_PAD_RIGHT);
00413         }
00414 
00415         if (iconv_strpos($number, '-') !== false) {
00416             $number = iconv_substr($number, 1);
00417         }
00418         $group  = iconv_strrpos($format, ',');
00419         $group2 = iconv_strpos ($format, ',');
00420         $point  = iconv_strpos ($format, '0');
00421         // Add fraction
00422         $rest = "";
00423         if (iconv_strpos($format, '.')) {
00424             $rest   = iconv_substr($format, iconv_strpos($format, '.') + 1);
00425             $length = iconv_strlen($rest);
00426             for($x = 0; $x < $length; ++$x) {
00427                 if (($rest[0] == '0') || ($rest[0] == '#')) {
00428                     $rest = iconv_substr($rest, 1);
00429                 }
00430             }
00431             $format = iconv_substr($format, 0, iconv_strlen($format) - iconv_strlen($rest));
00432         }
00433 
00434         if ($options['precision'] == '0') {
00435             if (iconv_strrpos($format, '-') != 0) {
00436                 $format = iconv_substr($format, 0, $point)
00437                         . iconv_substr($format, iconv_strrpos($format, '#') + 2);
00438             } else {
00439                 $format = iconv_substr($format, 0, $point);
00440             }
00441         } else {
00442             $format = iconv_substr($format, 0, $point) . $symbols['decimal']
00443                                . iconv_substr($prec, 2);
00444         }
00445 
00446         $format .= $rest;
00447         // Add seperation
00448         if ($group == 0) {
00449             // no seperation
00450             $format = $number . iconv_substr($format, $point);
00451         } else if ($group == $group2) {
00452             // only 1 seperation
00453             $seperation = ($point - $group);
00454             for ($x = iconv_strlen($number); $x > $seperation; $x -= $seperation) {
00455                 if (iconv_substr($number, 0, $x - $seperation) !== "") {
00456                     $number = iconv_substr($number, 0, $x - $seperation) . $symbols['group']
00457                             . iconv_substr($number, $x - $seperation);
00458                 }
00459             }
00460             $format = iconv_substr($format, 0, iconv_strpos($format, '#')) . $number . iconv_substr($format, $point);
00461         } else {
00462 
00463             // 2 seperations
00464             if (iconv_strlen($number) > ($point - $group)) {
00465                 $seperation = ($point - $group);
00466                 $number = iconv_substr($number, 0, iconv_strlen($number) - $seperation) . $symbols['group']
00467                         . iconv_substr($number, iconv_strlen($number) - $seperation);
00468 
00469                 if ((iconv_strlen($number) - 1) > ($point - $group + 1)) {
00470                     $seperation2 = ($group - $group2 - 1);
00471                     for ($x = iconv_strlen($number) - $seperation2 - 2; $x > $seperation2; $x -= $seperation2) {
00472                         $number = iconv_substr($number, 0, $x - $seperation2) . $symbols['group']
00473                                 . iconv_substr($number, $x - $seperation2);
00474                     }
00475                 }
00476 
00477             }
00478             $format = iconv_substr($format, 0, iconv_strpos($format, '#')) . $number . iconv_substr($format, $point);
00479         }
00480         // set negative sign
00481         if (call_user_func(Zend_Locale_Math::$comp, $value, 0, $options['precision']) < 0) {
00482             if (iconv_strpos($format, '-') === false) {
00483                 $format = $symbols['minus'] . $format;
00484             } else {
00485                 $format = str_replace('-', $symbols['minus'], $format);
00486             }
00487         }
00488 
00489         return (string) $format;
00490     }
00491 
00499     public static function isNumber($input, array $options = array())
00500     {
00501         $options = self::_checkOptions($options) + self::$_options;
00502 
00503         // Get correct signs for this locale
00504         $symbols = Zend_Locale_Data::getList($options['locale'],'symbols');
00505 
00506         $regexs = Zend_Locale_Format::_getRegexForType('decimalnumber', $options);
00507         $regexs = array_merge($regexs, Zend_Locale_Format::_getRegexForType('scientificnumber', $options));
00508         foreach ($regexs as $regex) {
00509             preg_match($regex, $input, $found);
00510             if (isset($found[0])) {
00511                 return true;
00512             }
00513         }
00514 
00515         return false;
00516     }
00517 
00524     private static function _getRegexForType($type, $options)
00525     {
00526         $decimal  = Zend_Locale_Data::getContent($options['locale'], $type);
00527         $decimal  = preg_replace('/[^#0,;\.\-Ee]/', '',$decimal);
00528         $patterns = explode(';', $decimal);
00529 
00530         if (count($patterns) == 1) {
00531             $patterns[1] = '-' . $patterns[0];
00532         }
00533 
00534         $symbols = Zend_Locale_Data::getList($options['locale'],'symbols');
00535 
00536         foreach($patterns as $pkey => $pattern) {
00537             $regex[$pkey]  = '/^';
00538             $rest   = 0;
00539             $end    = null;
00540             if (strpos($pattern, '.') !== false) {
00541                 $end     = substr($pattern, strpos($pattern, '.') + 1);
00542                 $pattern = substr($pattern, 0, -strlen($end) - 1);
00543             }
00544 
00545             if (strpos($pattern, ',') !== false) {
00546                 $parts = explode(',', $pattern);
00547                 $count = count($parts);
00548                 foreach($parts as $key => $part) {
00549                     switch ($part) {
00550                         case '#':
00551                         case '-#':
00552                             if ($part[0] == '-') {
00553                                 $regex[$pkey] .= '[' . $symbols['minus'] . '-]{0,1}';
00554                             } else {
00555                                 $regex[$pkey] .= '[' . $symbols['plus'] . '+]{0,1}';
00556                             }
00557 
00558                             if (($parts[$key + 1]) == '##0')  {
00559                                 $regex[$pkey] .= '[0-9]{1,3}';
00560                             } else if (($parts[$key + 1]) == '##') {
00561                                 $regex[$pkey] .= '[0-9]{1,2}';
00562                             } else {
00563                                 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 1):"' . $pattern . '"');
00564                             }
00565                             break;
00566                         case '##':
00567                             if ($parts[$key + 1] == '##0') {
00568                                 $regex[$pkey] .=  '(\\' . $symbols['group'] . '{0,1}[0-9]{2})*';
00569                             } else {
00570                                 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 2):"' . $pattern . '"');
00571                             }
00572                             break;
00573                         case '##0':
00574                             if ($parts[$key - 1] == '##') {
00575                                 $regex[$pkey] .= '[0-9]';
00576                             } else if (($parts[$key - 1] == '#') || ($parts[$key - 1] == '-#')) {
00577                                 $regex[$pkey] .= '(\\' . $symbols['group'] . '{0,1}[0-9]{3})*';
00578                             } else {
00579                                 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 3):"' . $pattern . '"');
00580                             }
00581                             break;
00582                         case '#0':
00583                             if ($key == 0) {
00584                                 $regex[$pkey] .= '[0-9]*';
00585                             } else {
00586                                 throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 4):"' . $pattern . '"');
00587                             }
00588                             break;
00589                     }
00590                 }
00591             }
00592 
00593             if (strpos($pattern, 'E') !== false) {
00594                 if (($pattern == '#E0') || ($pattern == '#E00')) {
00595                     $regex[$pkey] .= '[' . $symbols['plus']. '+]{0,1}[0-9]{1,}(\\' . $symbols['decimal'] . '[0-9]{1,})*[eE][' . $symbols['plus']. '+]{0,1}[0-9]{1,}';
00596                 } else if (($pattern == '-#E0') || ($pattern == '-#E00')) {
00597                     $regex[$pkey] .= '[' . $symbols['minus']. '-]{0,1}[0-9]{1,}(\\' . $symbols['decimal'] . '[0-9]{1,})*[eE][' . $symbols['minus']. '-]{0,1}[0-9]{1,}';
00598                 } else {
00599                     throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 5):"' . $pattern . '"');
00600                 }
00601             }
00602 
00603             if (!empty($end)) {
00604                 if ($end == '###') {
00605                     $regex[$pkey] .= '(\\' . $symbols['decimal'] . '{1}[0-9]{1,}){0,1}';
00606                 } else if ($end == '###-') {
00607                     $regex[$pkey] .= '(\\' . $symbols['decimal'] . '{1}[0-9]{1,}){0,1}[' . $symbols['minus']. '-]';
00608                 } else {
00609                     throw new Zend_Locale_Exception('Unsupported token for numberformat (Pos 6):"' . $pattern . '"');
00610                 }
00611             }
00612 
00613             $regex[$pkey] .= '$/';
00614         }
00615 
00616         return $regex;
00617     }
00618 
00625     private static function _floatalize($value)
00626     {
00627         $value = strtoupper($value);
00628         if (strpos($value, 'E') === false) {
00629             return $value;
00630         }
00631 
00632         $number = substr($value, 0, strpos($value, 'E'));
00633         if (strpos($number, '.') !== false) {
00634             $post   = strlen(substr($number, strpos($number, '.') + 1));
00635             $mantis = substr($value, strpos($value, 'E') + 1);
00636             if ($mantis < 0) {
00637                 $post += abs((int) $mantis);
00638             }
00639 
00640             $value = number_format($value, $post, '.', '');
00641         } else {
00642             $value = number_format($value, 0, '.', '');
00643         }
00644 
00645         return $value;
00646     }
00647 
00655     public static function getFloat($input, array $options = array())
00656     {
00657         return floatval(self::getNumber($input, $options));
00658     }
00659 
00668     public static function toFloat($value, array $options = array())
00669     {
00670         $options['number_format'] = Zend_Locale_Format::STANDARD;
00671         return self::toNumber($value, $options);
00672     }
00673 
00682     public static function isFloat($value, array $options = array())
00683     {
00684         return self::isNumber($value, $options);
00685     }
00686 
00703     public static function getInteger($input, array $options = array())
00704     {
00705         $options['precision'] = 0;
00706         return intval(self::getFloat($input, $options));
00707     }
00708 
00716     public static function toInteger($value, array $options = array())
00717     {
00718         $options['precision'] = 0;
00719         $options['number_format'] = Zend_Locale_Format::STANDARD;
00720         return self::toNumber($value, $options);
00721     }
00722 
00730     public static function isInteger($value, array $options = array())
00731     {
00732         if (!self::isNumber($value, $options)) {
00733             return false;
00734         }
00735 
00736         if (self::getInteger($value, $options) == self::getFloat($value, $options)) {
00737             return true;
00738         }
00739 
00740         return false;
00741     }
00742 
00755     public static function convertPhpToIsoFormat($format)
00756     {
00757         $convert = array('d' => 'dd'  , 'D' => 'EE'  , 'j' => 'd'   , 'l' => 'EEEE', 'N' => 'e'   , 'S' => 'SS'  ,
00758                          'w' => 'eee' , 'z' => 'D'   , 'W' => 'ww'  , 'F' => 'MMMM', 'm' => 'MM'  , 'M' => 'MMM' ,
00759                          'n' => 'M'   , 't' => 'ddd' , 'L' => 'l'   , 'o' => 'YYYY', 'Y' => 'yyyy', 'y' => 'yy'  ,
00760                          'a' => 'a'   , 'A' => 'a'   , 'B' => 'B'   , 'g' => 'h'   , 'G' => 'H'   , 'h' => 'hh'  ,
00761                          'H' => 'HH'  , 'i' => 'mm'  , 's' => 'ss'  , 'e' => 'zzzz', 'I' => 'I'   , 'O' => 'Z'   ,
00762                          'P' => 'ZZZZ', 'T' => 'z'   , 'Z' => 'X'   , 'c' => 'yyyy-MM-ddTHH:mm:ssZZZZ',
00763                          'r' => 'r'   , 'U' => 'U');
00764         $values = str_split($format);
00765         foreach ($values as $key => $value) {
00766             if (isset($convert[$value]) === true) {
00767                 $values[$key] = $convert[$value];
00768             }
00769         }
00770         return join($values);
00771     }
00772 
00780     private static function _parseDate($date, $options)
00781     {
00782         $options = self::_checkOptions($options) + self::$_options;
00783         $test = array('h', 'H', 'm', 's', 'y', 'Y', 'M', 'd', 'D', 'E', 'S', 'l', 'B', 'I',
00784                        'X', 'r', 'U', 'G', 'w', 'e', 'a', 'A', 'Z', 'z', 'v');
00785 
00786         $format = $options['date_format'];
00787         $number = $date; // working copy
00788         $result['date_format'] = $format; // save the format used to normalize $number (convenience)
00789         $result['locale'] = $options['locale']; // save the locale used to normalize $number (convenience)
00790 
00791         $day   = iconv_strpos($format, 'd');
00792         $month = iconv_strpos($format, 'M');
00793         $year  = iconv_strpos($format, 'y');
00794         $hour  = iconv_strpos($format, 'H');
00795         $min   = iconv_strpos($format, 'm');
00796         $sec   = iconv_strpos($format, 's');
00797         $am    = null;
00798         if ($hour === false) {
00799             $hour = iconv_strpos($format, 'h');
00800         }
00801         if ($year === false) {
00802             $year = iconv_strpos($format, 'Y');
00803         }
00804         if ($day === false) {
00805             $day = iconv_strpos($format, 'E');
00806             if ($day === false) {
00807                 $day = iconv_strpos($format, 'D');
00808             }
00809         }
00810 
00811         if ($day !== false) {
00812             $parse[$day]   = 'd';
00813             if (!empty($options['locale']) && ($options['locale'] !== 'root') &&
00814                 (!is_object($options['locale']) || ((string) $options['locale'] !== 'root'))) {
00815                 // erase day string
00816                     $daylist = Zend_Locale_Data::getList($options['locale'], 'day');
00817                 foreach($daylist as $key => $name) {
00818                     if (iconv_strpos($number, $name) !== false) {
00819                         $number = str_replace($name, "EEEE", $number);
00820                         break;
00821                     }
00822                 }
00823             }
00824         }
00825         $position = false;
00826 
00827         if ($month !== false) {
00828             $parse[$month] = 'M';
00829             if (!empty($options['locale']) && ($options['locale'] !== 'root') &&
00830                 (!is_object($options['locale']) || ((string) $options['locale'] !== 'root'))) {
00831                     // prepare to convert month name to their numeric equivalents, if requested,
00832                     // and we have a $options['locale']
00833                     $position = self::_replaceMonth($number, Zend_Locale_Data::getList($options['locale'],
00834                         'month'));
00835                 if ($position === false) {
00836                     $position = self::_replaceMonth($number, Zend_Locale_Data::getList($options['locale'],
00837                         'month', array('gregorian', 'format', 'abbreviated')));
00838                 }
00839             }
00840         }
00841         if ($year !== false) {
00842             $parse[$year]  = 'y';
00843         }
00844         if ($hour !== false) {
00845             $parse[$hour] = 'H';
00846         }
00847         if ($min !== false) {
00848             $parse[$min] = 'm';
00849         }
00850         if ($sec !== false) {
00851             $parse[$sec] = 's';
00852         }
00853 
00854         if (empty($parse)) {
00855             require_once 'Zend/Locale/Exception.php';
00856             throw new Zend_Locale_Exception("Unknown date format, neither date nor time in '" . $format . "' found");
00857         }
00858         ksort($parse);
00859 
00860         // get daytime
00861         if (iconv_strpos($format, 'a') !== false) {
00862             if (iconv_strpos(strtoupper($number), strtoupper(Zend_Locale_Data::getContent($options['locale'], 'am'))) !== false) {
00863                 $am = true;
00864             } else if (iconv_strpos(strtoupper($number), strtoupper(Zend_Locale_Data::getContent($options['locale'], 'pm'))) !== false) {
00865                 $am = false;
00866             }
00867         }
00868 
00869         // split number parts
00870         $split = false;
00871         preg_match_all('/\d+/u', $number, $splitted);
00872 
00873         if (count($splitted[0]) == 0) {
00874             require_once 'Zend/Locale/Exception.php';
00875             throw new Zend_Locale_Exception("No date part in '$date' found.");
00876         }
00877         if (count($splitted[0]) == 1) {
00878             $split = 0;
00879         }
00880         $cnt = 0;
00881         foreach($parse as $key => $value) {
00882 
00883             switch($value) {
00884                 case 'd':
00885                     if ($split === false) {
00886                         if (count($splitted[0]) > $cnt) {
00887                             $result['day']    = $splitted[0][$cnt];
00888                         }
00889                     } else {
00890                         $result['day'] = iconv_substr($splitted[0][0], $split, 2);
00891                         $split += 2;
00892                     }
00893                     ++$cnt;
00894                     break;
00895                 case 'M':
00896                     if ($split === false) {
00897                         if (count($splitted[0]) > $cnt) {
00898                             $result['month']  = $splitted[0][$cnt];
00899                         }
00900                     } else {
00901                         $result['month'] = iconv_substr($splitted[0][0], $split, 2);
00902                         $split += 2;
00903                     }
00904                     ++$cnt;
00905                     break;
00906                 case 'y':
00907                     $length = 2;
00908                     if ((iconv_substr($format, $year, 4) == 'yyyy')
00909                      || (iconv_substr($format, $year, 4) == 'YYYY')) {
00910                         $length = 4;
00911                     }
00912 
00913                     if ($split === false) {
00914                         if (count($splitted[0]) > $cnt) {
00915                             $result['year']   = $splitted[0][$cnt];
00916                         }
00917                     } else {
00918                         $result['year']   = iconv_substr($splitted[0][0], $split, $length);
00919                         $split += $length;
00920                     }
00921 
00922                     ++$cnt;
00923                     break;
00924                 case 'H':
00925                     if ($split === false) {
00926                         if (count($splitted[0]) > $cnt) {
00927                             $result['hour']   = $splitted[0][$cnt];
00928                         }
00929                     } else {
00930                         $result['hour']   = iconv_substr($splitted[0][0], $split, 2);
00931                         $split += 2;
00932                     }
00933                     ++$cnt;
00934                     break;
00935                 case 'm':
00936                     if ($split === false) {
00937                         if (count($splitted[0]) > $cnt) {
00938                             $result['minute'] = $splitted[0][$cnt];
00939                         }
00940                     } else {
00941                         $result['minute'] = iconv_substr($splitted[0][0], $split, 2);
00942                         $split += 2;
00943                     }
00944                     ++$cnt;
00945                     break;
00946                 case 's':
00947                     if ($split === false) {
00948                         if (count($splitted[0]) > $cnt) {
00949                             $result['second'] = $splitted[0][$cnt];
00950                         }
00951                     } else {
00952                         $result['second'] = iconv_substr($splitted[0][0], $split, 2);
00953                         $split += 2;
00954                     }
00955                     ++$cnt;
00956                     break;
00957             }
00958         }
00959 
00960         // AM/PM correction
00961         if ($hour !== false) {
00962             if (($am === true) and ($result['hour'] == 12)){
00963                 $result['hour'] = 0;
00964             } else if (($am === false) and ($result['hour'] != 12)) {
00965                 $result['hour'] += 12;
00966             }
00967         }
00968 
00969         if ($options['fix_date'] === true) {
00970             $result['fixed'] = 0; // nothing has been "fixed" by swapping date parts around (yet)
00971         }
00972 
00973         if ($day !== false) {
00974             // fix false month
00975             if (isset($result['day']) and isset($result['month'])) {
00976                 if (($position !== false) and ((iconv_strpos($date, $result['day']) === false) or
00977                                                (isset($result['year']) and (iconv_strpos($date, $result['year']) === false)))) {
00978                     if ($options['fix_date'] !== true) {
00979                         require_once 'Zend/Locale/Exception.php';
00980                         throw new Zend_Locale_Exception("Unable to parse date '$date' using '" . $format
00981                             . "' (false month, $position, $month)");
00982                     }
00983                     $temp = $result['day'];
00984                     $result['day']   = $result['month'];
00985                     $result['month'] = $temp;
00986                     $result['fixed'] = 1;
00987                 }
00988             }
00989 
00990             // fix switched values d <> y
00991             if (isset($result['day']) and isset($result['year'])) {
00992                 if ($result['day'] > 31) {
00993                     if ($options['fix_date'] !== true) {
00994                         require_once 'Zend/Locale/Exception.php';
00995                         throw new Zend_Locale_Exception("Unable to parse date '$date' using '"
00996                                                       . $format . "' (d <> y)");
00997                     }
00998                     $temp = $result['year'];
00999                     $result['year'] = $result['day'];
01000                     $result['day']  = $temp;
01001                     $result['fixed'] = 2;
01002                 }
01003             }
01004 
01005             // fix switched values M <> y
01006             if (isset($result['month']) and isset($result['year'])) {
01007                 if ($result['month'] > 31) {
01008                     if ($options['fix_date'] !== true) {
01009                         require_once 'Zend/Locale/Exception.php';
01010                         throw new Zend_Locale_Exception("Unable to parse date '$date' using '"
01011                                                       . $format . "' (M <> y)");
01012                     }
01013                     $temp = $result['year'];
01014                     $result['year']  = $result['month'];
01015                     $result['month'] = $temp;
01016                     $result['fixed'] = 3;
01017                 }
01018             }
01019 
01020             // fix switched values M <> d
01021             if (isset($result['month']) and isset($result['day'])) {
01022                 if ($result['month'] > 12) {
01023                     if ($options['fix_date'] !== true || $result['month'] > 31) {
01024                         require_once 'Zend/Locale/Exception.php';
01025                         throw new Zend_Locale_Exception("Unable to parse date '$date' using '"
01026                                                       . $format . "' (M <> d)");
01027                     }
01028                     $temp = $result['day'];
01029                     $result['day']   = $result['month'];
01030                     $result['month'] = $temp;
01031                     $result['fixed'] = 4;
01032                 }
01033             }
01034         }
01035 
01036         if (isset($result['year'])) {
01037             if (((iconv_strlen($result['year']) == 2) && ($result['year'] < 10)) ||
01038                 (((iconv_strpos($format, 'yy') !== false) && (iconv_strpos($format, 'yyyy') === false)) ||
01039                 ((iconv_strpos($format, 'YY') !== false) && (iconv_strpos($format, 'YYYY') === false)))) {
01040                 if (($result['year'] >= 0) && ($result['year'] < 100)) {
01041                     if ($result['year'] < 70) {
01042                         $result['year'] = (int) $result['year'] + 100;
01043                     }
01044 
01045                     $result['year'] = (int) $result['year'] + 1900;
01046                 }
01047             }
01048         }
01049 
01050         return $result;
01051     }
01052 
01061     protected static function _replaceMonth(&$number, $monthlist)
01062     {
01063         // If $locale was invalid, $monthlist will default to a "root" identity
01064         // mapping for each month number from 1 to 12.
01065         // If no $locale was given, or $locale was invalid, do not use this identity mapping to normalize.
01066         // Otherwise, translate locale aware month names in $number to their numeric equivalents.
01067         $position = false;
01068         if ($monthlist && $monthlist[1] != 1) {
01069             foreach($monthlist as $key => $name) {
01070                 if (($position = iconv_strpos($number, $name)) !== false) {
01071                     $number   = str_ireplace($name, $key, $number);
01072                     return $position;
01073                 }
01074             }
01075         }
01076         return false;
01077     }
01078 
01086     public static function getDateFormat($locale = null)
01087     {
01088         $format = Zend_Locale_Data::getContent($locale, 'date');
01089         if (empty($format)) {
01090             require_once 'Zend/Locale/Exception.php';
01091             throw new Zend_Locale_Exception("failed to receive data from locale $locale");
01092         }
01093         return $format;
01094     }
01095 
01109     public static function getDate($date, array $options = array())
01110     {
01111         $options = self::_checkOptions($options) + self::$_options;
01112         if (empty($options['date_format'])) {
01113             $options['format_type'] = 'iso';
01114             $options['date_format'] = self::getDateFormat($options['locale']);
01115         }
01116         return self::_parseDate($date, $options);
01117     }
01118 
01128     public static function checkDateFormat($date, array $options = array())
01129     {
01130         try {
01131             $date = self::getDate($date, $options);
01132         } catch (Exception $e) {
01133             return false;
01134         }
01135 
01136         if (empty($options['date_format'])) {
01137             $options['format_type'] = 'iso';
01138             $options['date_format'] = self::getDateFormat($options['locale']);
01139         }
01140         $options = self::_checkOptions($options) + self::$_options;
01141 
01142         // day expected but not parsed
01143         if ((iconv_strpos($options['date_format'], 'd') !== false) and (!isset($date['day']) or ($date['day'] == ""))) {
01144             return false;
01145         }
01146 
01147         // month expected but not parsed
01148         if ((iconv_strpos($options['date_format'], 'M') !== false) and (!isset($date['month']) or ($date['month'] == ""))) {
01149             return false;
01150         }
01151 
01152         // year expected but not parsed
01153         if (((iconv_strpos($options['date_format'], 'Y') !== false) or
01154              (iconv_strpos($options['date_format'], 'y') !== false)) and (!isset($date['year']) or ($date['year'] == ""))) {
01155             return false;
01156         }
01157 
01158         // second expected but not parsed
01159         if ((iconv_strpos($options['date_format'], 's') !== false) and (!isset($date['second']) or ($date['second'] == ""))) {
01160             return false;
01161         }
01162 
01163         // minute expected but not parsed
01164         if ((iconv_strpos($options['date_format'], 'm') !== false) and (!isset($date['minute']) or ($date['minute'] == ""))) {
01165             return false;
01166         }
01167 
01168         // hour expected but not parsed
01169         if (((iconv_strpos($options['date_format'], 'H') !== false) or
01170              (iconv_strpos($options['date_format'], 'h') !== false)) and (!isset($date['hour']) or ($date['hour'] == ""))) {
01171             return false;
01172         }
01173         return true;
01174     }
01175 
01182     public static function getTimeFormat($locale = null)
01183     {
01184         $format = Zend_Locale_Data::getContent($locale, 'time');
01185         if (empty($format)) {
01186             require_once 'Zend/Locale/Exception.php';
01187             throw new Zend_Locale_Exception("failed to receive data from locale $locale");
01188         }
01189         return $format;
01190     }
01191 
01204     public static function getTime($time, array $options = array())
01205     {
01206         $options = self::_checkOptions($options) + self::$_options;
01207         if (empty($options['date_format'])) {
01208             $options['format_type'] = 'iso';
01209             $options['date_format'] = self::getTimeFormat($options['locale']);
01210         }
01211         return self::_parseDate($time, $options);
01212     }
01213 
01220     public static function getDateTimeFormat($locale = null)
01221     {
01222         $format = Zend_Locale_Data::getContent($locale, 'datetime');
01223         if (empty($format)) {
01224             require_once 'Zend/Locale/Exception.php';
01225             throw new Zend_Locale_Exception("failed to receive data from locale $locale");
01226         }
01227         return $format;
01228     }
01229 
01242     public static function getDateTime($datetime, array $options = array())
01243     {
01244         $options = self::_checkOptions($options) + self::$_options;
01245         if (empty($options['date_format'])) {
01246             $options['format_type'] = 'iso';
01247             $options['date_format'] = self::getDateTimeFormat($options['locale']);
01248         }
01249         return self::_parseDate($datetime, $options);
01250     }
01251 }

Generated on Thu Apr 19 2012 17:01:17 for openbiz by  doxygen 1.7.2