diff --git a/README.md b/README.md index 3cf378e..8267f58 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,19 @@ $timezones->findByIdentifier(iana: 'Asia/Tokyo'); # Timezone("Asia/Tokyo") $timezones->findByIdentifier(iana: 'Europe/London'); # null ``` +#### Finding a timezone by identifier with UTC fallback + +Searches for a specific IANA identifier within the collection. Returns UTC if not found. + +```php +use TinyBlocks\Time\Timezones; + +$timezones = Timezones::fromStrings('UTC', 'America/Sao_Paulo', 'Asia/Tokyo'); + +$timezones->findByIdentifierOrUtc(iana: 'Asia/Tokyo'); # Timezone("Asia/Tokyo") +$timezones->findByIdentifierOrUtc(iana: 'Europe/London'); # Timezone("UTC") +``` + #### Checking if a timezone exists in the collection ```php diff --git a/src/Timezones.php b/src/Timezones.php index f0f0750..d7f4cde 100644 --- a/src/Timezones.php +++ b/src/Timezones.php @@ -99,6 +99,17 @@ public function findByIdentifier(string $iana): ?Timezone ); } + /** + * Finds a Timezone by its IANA identifier, falling back to UTC if not found. + * + * @param string $iana The IANA timezone identifier to search for (e.g. America/Sao_Paulo). + * @return Timezone The matching Timezone, or UTC if not found in this collection. + */ + public function findByIdentifierOrUtc(string $iana): Timezone + { + return $this->findByIdentifier(iana: $iana) ?? Timezone::utc(); + } + /** * Returns all timezone identifiers as plain strings. * diff --git a/tests/TimezonesTest.php b/tests/TimezonesTest.php index b3a9356..77c977f 100644 --- a/tests/TimezonesTest.php +++ b/tests/TimezonesTest.php @@ -112,6 +112,30 @@ public function testTimezonesFindByIdentifierReturnsNullWhenNotFound(): void self::assertNull($found); } + public function testTimezonesFindByIdentifierOrUtcReturnsMatchingTimezone(): void + { + /** @Given a Timezones collection with multiple identifiers */ + $timezones = Timezones::fromStrings('UTC', 'America/Sao_Paulo', 'Asia/Tokyo'); + + /** @When searching for an existing identifier */ + $found = $timezones->findByIdentifierOrUtc(iana: 'Asia/Tokyo'); + + /** @Then the matching Timezone should be returned */ + self::assertSame('Asia/Tokyo', $found->value); + } + + public function testTimezonesFindByIdentifierOrUtcReturnsUtcWhenNotFound(): void + { + /** @Given a Timezones collection without Europe/London */ + $timezones = Timezones::fromStrings('America/Sao_Paulo', 'Asia/Tokyo'); + + /** @When searching for a non-existing identifier */ + $found = $timezones->findByIdentifierOrUtc(iana: 'Europe/London'); + + /** @Then UTC should be returned as fallback */ + self::assertSame('UTC', $found->value); + } + public function testTimezonesCountMatchesAllSize(): void { /** @Given a Timezones collection with four items */