Esempio n. 1
0
 /**
  * Format a unit string
  * @param int|float|string $number The unit amount
  * @param string $unit The unit identifier (eg 'duration/millisecond' or 'millisecond')
  * @param string $width = 'short' The format name; it can be 'long' (eg '3 milliseconds'), 'short' (eg '3 ms') or 'narrow' (eg '3ms'). You can also add a precision specifier ('long,2' or just '2')
  * @param string $locale = '' The locale to use. If empty we'll use the default locale set in \Punic\Data
  */
 public static function format($number, $unit, $width = 'short', $locale = '')
 {
     $data = \Punic\Data::get('units', $locale);
     $precision = null;
     if (is_int($width)) {
         $precision = $width;
         $width = 'short';
     } elseif (is_string($width) && preg_match('/^(?:(.*),)?([+\\-]?\\d+)$/', $width, $m)) {
         $precision = intval($m[2]);
         $width = $m[1];
         if (!strlen($width)) {
             $width = 'short';
         }
     }
     if (strpos($width, '_') === 0 || !array_key_exists($width, $data)) {
         $widths = array();
         foreach (array_keys($data) as $w) {
             if (strpos($w, '_') !== 0) {
                 $widths[] = $w;
             }
         }
         throw new Exception\ValueNotInList($width, $widths);
     }
     $data = $data[$width];
     if (strpos($unit, '/') === false) {
         $unitCategory = null;
         $unitID = null;
         foreach (array_keys($data) as $c) {
             if (strpos($c, '_') === false) {
                 if (array_key_exists($unit, $data[$c])) {
                     if (is_null($unitCategory)) {
                         $unitCategory = $c;
                         $unitID = $unit;
                     } else {
                         $unitCategory = null;
                         break;
                     }
                 }
             }
         }
     } else {
         list($unitCategory, $unitID) = explode('/', $unit, 2);
     }
     $rules = null;
     if (strpos($unit, '_') === false && !is_null($unitCategory) && !is_null($unitID) && array_key_exists($unitCategory, $data) && array_key_exists($unitID, $data[$unitCategory])) {
         $rules = $data[$unitCategory][$unitID];
     }
     if (is_null($rules)) {
         $units = array();
         foreach ($data as $c => $us) {
             if (strpos($c, '_') === false) {
                 foreach (array_keys($us) as $u) {
                     if (strpos($c, '_') === false) {
                         $units[] = "{$c}/{$u}";
                     }
                 }
             }
         }
         throw new \Punic\Exception\ValueNotInList($unit, $units);
     }
     $pluralRule = \Punic\Plural::getRule($number, $locale);
     //@codeCoverageIgnoreStart
     // These checks aren't necessary since $pluralRule should always be in $rules, but they don't hurt ;)
     if (!array_key_exists($pluralRule, $rules)) {
         if (array_key_exists('other', $rules)) {
             $pluralRule = 'other';
         } else {
             $availableRules = array_keys($rules);
             $pluralRule = $availableRules[0];
         }
     }
     //@codeCoverageIgnoreEnd
     return sprintf($rules[$pluralRule], \Punic\Number::format($number, $precision, $locale));
 }
Esempio n. 2
0
 /**
  * Describe an relative interval from $dateStart to $dateEnd (eg '2 days ago').
  * Only the largest differing unit is described, and the next smaller unit will be used
  * for rounding.
  *
  * @param \DateTime      $dateEnd   The terminal date
  * @param \DateTime|null $dateStart The anchor date, defaults to now. (if it has a timezone different than
  *                        $dateEnd, we'll use the one of $dateEnd)
  * @param string         $width     The format name; it can be '', 'short' or 'narrow'
  * @param string         $locale    The locale to use. If empty we'll use the default locale set in \Punic\Data
  *
  * @return string
  *
  * @throws \InvalidArgumentException
  */
 public static function describeRelativeInterval($dateEnd, $dateStart = null, $width = '', $locale = '')
 {
     if (!is_a($dateEnd, '\\DateTime')) {
         throw new \InvalidArgumentException('Not a DateTime object');
     }
     if (empty($dateStart) && $dateStart !== 0 && $dateStart !== '0') {
         $dateStart = new \DateTime('now');
     } elseif (!is_a($dateStart, '\\DateTime')) {
         throw new \InvalidArgumentException('Not a DateTime object');
     } else {
         $dateStart = clone $dateStart;
     }
     $dateStart->setTimezone($dateEnd->getTimezone());
     //$utc = new \DateTimeZone('UTC');
     //$dateEndUTC = new \DateTime($dateEnd->format('Y-m-d H:i:s'), $utc);
     //$dateStartUTC = new \DateTime($dateStart->format('Y-m-d H:i:s'), $utc);
     $parts = array();
     $data = Data::get('dateFields', $locale);
     $diff = $dateStart->diff($dateEnd, false);
     $past = (bool) $diff->invert;
     $value = 0;
     $key = '';
     if ($diff->y != 0) {
         $key = 'year';
         $value = $diff->y + ($diff->m > 6 ? 1 : 0);
     } elseif ($diff->m != 0) {
         $key = 'month';
         $value = $diff->m + ($diff->d > 15 ? 1 : 0);
     } elseif ($diff->d != 0) {
         $key = 'day';
         $value = $diff->d + ($diff->h > 12 ? 1 : 0);
     } elseif ($diff->h != 0) {
         $key = 'hour';
         $value = $diff->h + ($diff->i > 30 ? 1 : 0);
     } elseif ($diff->i != 0) {
         $key = 'minute';
         $value = $diff->i + ($diff->s > 30 ? 1 : 0);
     } elseif ($diff->s != 0) {
         $key = 'second';
         $value = $diff->s;
     }
     if ($value == 0) {
         $key = 'second';
         $relKey = 'relative-type-0';
         $relPattern = null;
     } elseif ($key === 'day' && $value > 1 && $value < 7) {
         $dow = $dateEnd->format('N') - 1;
         $days = array('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun');
         $key = $days[$dow];
         $relKey = $past ? "relative-type--1" : "relative-type-1";
         $relPattern = null;
     } else {
         if ($value == 1 && isset($data[$key]['relative-type--1'])) {
             $relKey = $past ? 'relative-type--1' : 'relative-type-1';
             $relPattern = null;
         } else {
             $relKey = $past ? 'relativeTime-type-past' : 'relativeTime-type-future';
             $rule = Plural::getRule($value, $locale);
             $relPattern = 'relativeTimePattern-count-' . $rule;
         }
     }
     if (!empty($width) && array_key_exists($key . '-' . $width, $data)) {
         $key .= '-' . $width;
     }
     if (empty($relPattern)) {
         $relativeString = $data[$key][$relKey];
     } else {
         $tempString = $data[$key][$relKey][$relPattern];
         $tempString = str_replace('{0}', '%d', $tempString);
         $relativeString = sprintf($tempString, $value);
     }
     return $relativeString;
 }