getMultiplierToSeconds(); $this->nanoseconds = (int) round($seconds * 1_000_000_000); } /** * Create Duration directly from nanoseconds for maximum precision */ public static function fromNanoseconds(int $nanoseconds): self { return new self($nanoseconds, TimeUnit::NANOSECOND); } // Factory Methods public static function fromSeconds(float $seconds): self { return new self($seconds, TimeUnit::SECOND); } public static function fromUnit(float $value, TimeUnit $unit): self { return new self($value, $unit); } public static function fromMilliseconds(float $milliseconds): self { return self::fromUnit($milliseconds, TimeUnit::MILLISECOND); } public static function fromMicroseconds(float $microseconds): self { return self::fromUnit($microseconds, TimeUnit::MICROSECOND); } public static function fromMinutes(float $minutes): self { return self::fromUnit($minutes, TimeUnit::MINUTE); } public static function fromHours(float $hours): self { return self::fromUnit($hours, TimeUnit::HOUR); } public static function fromDays(float $days): self { return self::fromUnit($days, TimeUnit::DAY); } public static function between(Timestamp $timestamp, Timestamp $other): self { return $timestamp->diff($other); } // Parse from human-readable strings public static function parse(string $value): self { $value = trim($value); if (preg_match('/^(\d+(?:\.\d+)?)\s*([a-zA-Z]*)$/', $value, $matches)) { $number = (float) $matches[1]; $unitString = $matches[2] ?: 's'; $unit = TimeUnit::fromString($unitString); return self::fromUnit($number, $unit); } throw new InvalidArgumentException("Invalid duration format: $value"); } // Conversion Methods public function toSeconds(): float { return $this->nanoseconds / 1_000_000_000; } public function toNanoseconds(): int { return $this->nanoseconds; } public function toUnit(TimeUnit $unit, int $precision = 2): float { $seconds = $this->nanoseconds / 1_000_000_000; return round($seconds / $unit->getMultiplierToSeconds(), $precision); } public function toMilliseconds(int $precision = 0): float { return $this->toUnit(TimeUnit::MILLISECOND, $precision); } public function toMicroseconds(int $precision = 0): float { return $this->toUnit(TimeUnit::MICROSECOND, $precision); } public function toMinutes(int $precision = 0): float { return $this->toUnit(TimeUnit::MINUTE, $precision); } public function toHours(int $precision = 0): float { return $this->toUnit(TimeUnit::HOUR, $precision); } // Human-readable format public function toHumanReadable(): string { if ($this->nanoseconds === 0) { return '0s'; } $seconds = $this->nanoseconds / 1_000_000_000; $unit = TimeUnit::bestUnitFor($seconds); $value = $this->toUnit($unit); return $value . ' ' . $unit->value; } // Arithmetic Operations public function add(Duration $other): self { return new self($this->nanoseconds + $other->nanoseconds); } public function subtract(Duration $other): self { $result = $this->nanoseconds - $other->nanoseconds; if ($result < 0) { throw new InvalidArgumentException('Subtraction would result in negative duration'); } return new self($result); } public function multiply(float $factor): self { if ($factor < 0) { throw new InvalidArgumentException('Factor cannot be negative'); } return new self((int) round($this->nanoseconds * $factor)); } // Comparison Methods public function equals(Duration $other): bool { return $this->nanoseconds === $other->nanoseconds; } public function greaterThan(Duration $other): bool { return $this->nanoseconds > $other->nanoseconds; } public function lessThan(Duration $other): bool { return $this->nanoseconds < $other->nanoseconds; } // Utility Methods public function isZero(): bool { return $this->nanoseconds === 0; } public function isNotZero(): bool { return !$this->isZero(); } // Framework Integration public function toCacheSeconds(): int { return (int) ceil($this->nanoseconds / 1_000_000_000); } public function toTimeoutSeconds(): int { return (int) ceil($this->nanoseconds / 1_000_000_000); } public function __toString(): string { return $this->toHumanReadable(); } // Common constants public static function zero(): self { return new self(0); } public static function oneSecond(): self { return new self(1, TimeUnit::SECOND); } public static function oneMinute(): self { return self::fromMinutes(1); } public static function oneHour(): self { return self::fromHours(1); } }