Files
michaelschiemer/src/Framework/Core/ValueObjects/Duration.php
Michael Schiemer 2a7b90312f chore(deploy): add prod env template, improve ansible deploy, prune old workflows
- Add deployment/ansible/templates/.env.production.j2 used by secrets playbook
- Enhance deploy-update.yml to read registry creds from vault or CI
- Update production-deploy workflow to pass registry credentials to Ansible
- Remove obsolete GitHub-style workflows under .gitea (conflicted naming)

Why: make the production pipeline executable end-to-end with Ansible and
consistent secrets handling; avoid legacy CI configs interfering.
2025-10-30 21:38:28 +01:00

232 lines
5.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Core\ValueObjects;
use InvalidArgumentException;
final readonly class Duration
{
private int $nanoseconds;
public function __construct(
float|int $value,
TimeUnit $unit = TimeUnit::NANOSECOND,
) {
if ($value < 0) {
throw new InvalidArgumentException('Duration cannot be negative');
}
$seconds = $value * $unit->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);
}
}