Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 11 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
* [Alpha3Code](#alpha3code)
* [Country](#country-1)
* [Timezones](#timezones)
* [Timezone](#timezone)
* [License](#license)
* [Contributing](#contributing)

Expand Down Expand Up @@ -141,8 +140,8 @@ $country->alpha3->value; # USA

### Timezones

Every `Country` includes an immutable `Timezones` collection, built from the IANA timezone database (via PHP's ICU
integration).
Every `Country` includes an immutable `CountryTimezones` collection, built from the IANA timezone database (via PHP's
ICU integration).

```php
use TinyBlocks\Country\Country;
Expand All @@ -160,6 +159,11 @@ $country->timezones->toStrings(); # ["America/Noronha", "America/Belem", "Ameri
Returns all `Timezone` objects for the country:

```php
use TinyBlocks\Country\Country;
use TinyBlocks\Country\Alpha2Code;

$country = Country::from(alphaCode: Alpha2Code::BRAZIL);

$country->timezones->all(); # [Timezone("America/Noronha"), Timezone("America/Belem"), ...]
```

Expand All @@ -178,18 +182,18 @@ $country = Country::from(alphaCode: Alpha2Code::BOUVET_ISLAND);
$country->timezones->default(); # Timezone("UTC")
```

#### Finding a timezone by identifier
#### Finding a timezone by identifier with UTC fallback

Searches for a specific IANA identifier within the country's timezones:
Searches for a specific IANA identifier within the country's timezones. Returns UTC if not found.

```php
use TinyBlocks\Country\Country;
use TinyBlocks\Country\Alpha2Code;

$country = Country::from(alphaCode: Alpha2Code::UNITED_STATES_OF_AMERICA);

$country->timezones->findByIdentifier(iana: 'America/New_York'); # Timezone("America/New_York")
$country->timezones->findByIdentifier(iana: 'Asia/Tokyo'); # null
$country->timezones->findByIdentifierOrUtc(iana: 'America/New_York'); # Timezone("America/New_York")
$country->timezones->findByIdentifierOrUtc(iana: 'Asia/Tokyo'); # Timezone("UTC")
```

#### Checking if a timezone belongs to the country
Expand All @@ -204,29 +208,6 @@ $country->timezones->contains(iana: 'Asia/Tokyo'); # true
$country->timezones->contains(iana: 'America/New_York'); # false
```

### Timezone

A `Timezone` is a Value Object representing a single valid IANA timezone identifier.

```php
use TinyBlocks\Country\Timezone;

$timezone = Timezone::from(identifier: 'America/Sao_Paulo');

$timezone->value; # America/Sao_Paulo
$timezone->toString(); # America/Sao_Paulo
```

Creating a UTC timezone:

```php
use TinyBlocks\Country\Timezone;

$timezone = Timezone::utc();

$timezone->value; # UTC
```

<div id='license'></div>

## License
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"require": {
"php": "^8.5",
"tiny-blocks/time": "^1.1",
Comment thread
gustavofreze marked this conversation as resolved.
"tiny-blocks/value-object": "^3.2"
},
"require-dev": {
Expand Down
4 changes: 2 additions & 2 deletions src/Country.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ private function __construct(
public readonly string $name,
public readonly Alpha2Code $alpha2,
public readonly Alpha3Code $alpha3,
public readonly Timezones $timezones
public readonly CountryTimezones $timezones
Comment thread
gustavofreze marked this conversation as resolved.
) {
}

Expand Down Expand Up @@ -55,7 +55,7 @@ public static function from(AlphaCode $alphaCode, ?string $name = null): static
name: $resolvedName,
alpha2: $alpha2,
alpha3: $alpha3,
timezones: Timezones::fromAlpha2(alpha2: $alpha2)
timezones: CountryTimezones::fromAlpha2(alpha2: $alpha2)
);
}

Expand Down
72 changes: 32 additions & 40 deletions src/Timezones.php → src/CountryTimezones.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,38 @@

use Countable;
use TinyBlocks\Country\Internal\TimezoneCatalog;
use TinyBlocks\Time\Timezone;
use TinyBlocks\Time\Timezones;
use TinyBlocks\Vo\ValueObject;
use TinyBlocks\Vo\ValueObjectBehavior;

/**
* Immutable collection of Timezone objects for a country.
*
* Built from PHP's ICU/IANA timezone database — the authoritative source for timezone data.
* The first element is considered the default/primary timezone for the country.
*/
final readonly class Timezones implements Countable
final readonly class CountryTimezones implements ValueObject, Countable
{
/**
* @param list<Timezone> $items All timezone objects for the country.
* @param Timezone $default The default/primary timezone (first in the IANA list, or UTC as fallback).
*/
private function __construct(private array $items, private Timezone $default)
use ValueObjectBehavior;

private function __construct(private Timezones $timezones, private Timezone $default)
{
}

/**
* Creates a Timezones collection from an Alpha-2 country code.
* Creates a CountryTimezones instance from an Alpha-2 country code.
*
* @param Alpha2Code $alpha2 The two-letter country code.
* @return Timezones The timezones collection for the given country.
* @param Alpha2Code $alpha2 The Alpha-2 country code (e.g. "US" for United States).
* @return CountryTimezones A new CountryTimezones instance containing the timezones for the specified country.
*/
public static function fromAlpha2(Alpha2Code $alpha2): Timezones
public static function fromAlpha2(Alpha2Code $alpha2): CountryTimezones
{
$items = array_map(
static fn(string $id): Timezone => Timezone::from(identifier: $id),
TimezoneCatalog::forAlpha2(alpha2Value: $alpha2->value)
);
$identifiers = TimezoneCatalog::forAlpha2(alpha2Value: $alpha2->value);
$timezones = Timezones::fromStrings(...$identifiers);
$default = $timezones->all()[0] ?? Timezone::utc();

return new Timezones(items: $items, default: $items[0] ?? Timezone::utc());
return new CountryTimezones(timezones: $timezones, default: $default);
}

/**
Expand All @@ -46,7 +47,7 @@ public static function fromAlpha2(Alpha2Code $alpha2): Timezones
*/
public function all(): array
{
return $this->items;
return $this->timezones->all();
}

/**
Expand All @@ -56,7 +57,7 @@ public function all(): array
*/
public function count(): int
{
return count($this->items);
return $this->timezones->count();
}

/**
Expand All @@ -73,43 +74,34 @@ public function default(): Timezone
}

/**
* Checks whether the given IANA identifier belongs to this country's timezones.
* Returns all timezone identifiers as plain strings.
*
* @param string $iana The IANA timezone identifier to check (e.g. America/New_York).
* @return bool True if the identifier belongs to this country, false otherwise.
* @return list<string> The list of IANA timezone identifier strings.
*/
public function contains(string $iana): bool
public function toStrings(): array
{
return array_any(
$this->items,
static fn(Timezone $timezone): bool => $timezone->value === $iana
);
return $this->timezones->toStrings();
}

/**
* Finds a Timezone by its IANA identifier.
* Checks whether the given IANA identifier belongs to this country's timezones.
*
* @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 country.
* @param string $iana The IANA timezone identifier to check (e.g. America/New_York).
* @return bool True if the identifier belongs to this country, false otherwise.
*/
public function findByIdentifier(string $iana): Timezone
public function contains(string $iana): bool
{
return array_find(
$this->items,
static fn(Timezone $timezone): bool => $timezone->value === $iana
) ?? Timezone::utc();
return $this->timezones->contains(iana: $iana);
}

/**
* Returns all timezone identifiers as plain strings.
* Finds a Timezone object by its IANA identifier.
*
* @return list<string> The list of IANA timezone identifier strings.
* @param string $iana The IANA timezone identifier to find (e.g. America/New_York).
* @return Timezone The corresponding Timezone object if found, or UTC if not found.
*/
public function toStrings(): array
public function findByIdentifierOrUtc(string $iana): Timezone
{
return array_map(
static fn(Timezone $timezone): string => $timezone->toString(),
$this->items
);
return $this->timezones->findByIdentifierOrUtc(iana: $iana);
Comment thread
gustavofreze marked this conversation as resolved.
}
}
17 changes: 0 additions & 17 deletions src/Internal/Exceptions/InvalidTimezone.php

This file was deleted.

74 changes: 0 additions & 74 deletions src/Timezone.php

This file was deleted.

Loading