/** * {@inheritdoc} */ public static function toInternal($date, $format = null) { if (!in_array(strtolower($format), ['tai64', 'tai64n', 'tai64na', 'numeric'])) { $format = 'tai64na'; } if (substr(strtolower($format), 0, 5) == 'tai64') { $date = str_pad(str_pad($date, 16, '0', STR_PAD_LEFT), 32, '0', STR_PAD_RIGHT); $time = ['seconds' => gmp_strval(gmp_init('0x' . substr($date, 0, 16), 16), 10), 'nano' => gmp_strval(gmp_init('0x' . substr($date, 16, 8), 16), 10), 'atto' => gmp_strval(gmp_init('0x' . substr($date, 24, 8), 16), 10)]; } elseif (strtolower($format) == 'numeric') { list($time['seconds'], $frac) = explode('.', "{$date}."); $frac = str_pad($frac, 18, '0', STR_PAD_RIGHT); $time['nano'] = substr($frac, 0, 9); $time['atto'] = substr($frac, 9, 9); } if (BC::comp($time['seconds'], BC::pow(2, 63, 18), 18) >= 0) { $time = ['seconds' => BC::sub(BC::pow(2, 63, 18), 1, 0), 'nano' => '999999999', 'atto' => '999999999']; } elseif (BC::comp($time['seconds'], 0, 18) <= 0) { $time = ['seconds' => '0', 'nano' => '0', 'atto' => '0']; } return $time; }
/** * Compares the start time, end time, or duration of two Calends objects * * @api * * @param Calends $a One of the two Calends objects to compare times from * @param Calends $b One of the two Calends objects to compare times from * @param string $mode One of start, end, start-end, end-start, or duration * @return integer Values are -1 if a < b; 0 if a == b; +1 if a > b **/ public static function compare(Calends $a, Calends $b, $mode = 'start') { $times = static::getTimesByMode($a, $b, $mode); return BC::comp($times[0], $times[1], 18); }
public function carryOver(array $unitArray) { $myVal = $this->is_auxiliary ? 0 : BC::sub(Arr::get($unitArray, $this->internal_name, $this->uses_zero ? 0 : 1), $this->uses_zero ? 0 : 1, 18); $exprInverse = '({myVal} * {scale}) %% {scale}'; $exprNormal = '({myVal} - ({myVal} %% {scale})) / {scale}'; foreach ($this->scalesToMe()->get() as $unit) { $unitVal = BC::sub(Arr::get($unitArray, $unit->internal_name, $unit->uses_zero ? 0 : 1), $unit->uses_zero ? 0 : 1, 18); $unitAdjustment = 0; $myAdjustment = 0; if ($unit->scale_inverse) { $adjComp = 1; $unitExpr = $exprInverse; $myExpr = '{adjust} / {scale}'; } else { $adjComp = $myVal; $unitExpr = $exprNormal; $myExpr = '{adjust} * {scale}'; } if (!is_null($unit->scale_amount)) { $unitAdjustment = BC::parse($unitExpr, ['myVal' => $myVal, 'scale' => $unit->scale_amount], 18); $myAdjustment = BC::parse($myExpr, ['adjust' => $unitAdjustment, 'scale' => $unit->scale_amount], 18); } else { $lengths = $unit->lengths()->get(); $lCount = $lengths->count(); $lSum = $lengths->sum('scale_amount'); if ($lCount > 0) { $unitAdjustment = BC::add($unitAdjustment, BC::parse("({$unitExpr}) * {$lCount}", ['myVal' => $myVal, 'scale' => $lSum], 18), 18); $myAdjustment = BC::add($myAdjustment, BC::parse($myExpr, ['adjust' => BC::div($unitAdjustment, $lCount, 18), 'scale' => $lSum], 18), 18); for ($lNum = 0; BC::comp($adjComp, $myAdjustment) > 0 && BC::comp($myVal, $lengths[$lNum]->scale_amount) >= 0; $lNum = BC::parse("({$lNum} + 1) % {$lCount}", null, 0)) { $unitAdjustment = BC::add($unitAdjustment, 1, 18); $myAdjustment = BC::add($myAdjustment, $lengths[$lNum]->scale_amount, 18); } if (BC::comp($adjComp, $myAdjustment) < 0) { $unitAdjustment = BC::sub($unitAdjustment, 1, 18); $myAdjustment = BC::sub($myAdjustment, $lengths[BC::parse("({$lNum} - 1 + {$lCount}) % {$lCount}", null, 0)]->scale_amount, 18); } } } $unitArray[$unit->internal_name] = BC::add(BC::add($unitVal, $unitAdjustment, 18), $unit->uses_zero ? 0 : 1, 18); if (!$unit->is_auxiliary) { $unitArray[$this->internal_name] = $myVal = BC::add(BC::sub($myVal, $myAdjustment, 18), $this->uses_zero ? 0 : 1, 18); } $unitArray = $unit->carryOver($unitArray); } return $unitArray; }