cahuk / server-timezone
Compatible Clock that gets server time from IP-based geolocation
v1.0.0
2025-05-29 13:50 UTC
Requires
- php: >=8.3.0
- guzzlehttp/guzzle: ^7.9
- psr/clock: ^1.0
Requires (Dev)
- phpunit/phpunit: ^12.1.6
This package is auto-updated.
Last update: 2025-06-29 14:35:54 UTC
README
A PHP package to resolve the current time based on an IP address using various external GeoIP and time APIs.
Installation
composer require cahuk/server-timezone
Running Unit Tests
Before running tests, clone the repository and install dependencies:
composer install
composer test
Usage Example
Below is a single comprehensive example demonstrating different approaches to resolve time based on IP:
<?php require_once __DIR__ . '/../vendor/autoload.php'; use Psr\Http\Message\ResponseInterface; use Cahuk\ServerTimezone\Core\Services\TimeResolverService; use Cahuk\ServerTimezone\Infrastructure\TimeProvider\TimeResolverProvider; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\GeoIpTimeApiResolver; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\HttpClient\HttpConfig; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\IpFetcher\Api\IpApiFetcher; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\Services\TimeApiFetcherService; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\TimeFetcher\Api\HttpTimeFetcher; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\IpFetcher\Api\HttpIpFetcherResponse; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\IpFetcher\Api\Mappers\IpifyOrgIpMapper; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\TimeFetcher\Api\Mappers\TimeapiIoTimeMapper; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\IpFetcher\Api\HttpIpFetcherResponseInterface; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\IpFetcher\Api\Client\GuzzleHttpIpFetcherClient; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\TimeFetcher\Api\Mappers\IpgeolocationIoTimeMapper; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\TimeFetcher\Api\Client\GuzzleHttpTimeFetcherClient; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\IpFetcher\Api\HttpIpFetcherResponseMapperInterface; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\Services\TimeParametersMappers\DefaultMappingFields; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\Services\TimeParametersMappers\DefaultTimeParametersMappers; use Cahuk\ServerTimezone\Infrastructure\TimeResolver\GeoIpTimeResolver\Services\TimeParametersMappers\DefaultMappingTimeParameters; // ------------------------------------------------------------ // Example 1: Fetch current time for a known external IP address $timeServerHost1 = 'https://timeapi.io'; $timeServerUrl1 = '/api/time/current/ip'; $timeServerHeaders1 = ['Accept' => 'application/json']; $timeServerParams1 = ['ipAddress' => '89.151.31.13']; $apiTimeProvider1 = new TimeResolverProvider( new GeoIpTimeApiResolver( new HttpTimeFetcher( new GuzzleHttpTimeFetcherClient( new HttpConfig( $timeServerHost1, $timeServerUrl1, headers: $timeServerHeaders1, parameters: $timeServerParams1, ), new IpgeolocationIoTimeMapper() ) ) ) ); var_dump((new TimeResolverService($apiTimeProvider1))->resolveTime()->now()); // ------------------------------------------------------------ // Example 2: Use separate services to fetch IP and then time by IP $ipServerHost2 = 'https://api.ipify.org'; $ipServerUrl2 = ''; $timeServerHost2 = 'https://timeapi.io'; $timeServerUrl2 = '/api/time/current/ip'; $timeServerHeaders2 = ['Accept' => 'application/json']; $apiTimeProvider2 = new TimeResolverProvider( new GeoIpTimeApiResolver( new TimeApiFetcherService( new IpApiFetcher( new GuzzleHttpIpFetcherClient( new HttpConfig($ipServerHost2, $ipServerUrl2), new IpifyOrgIpMapper() ) ), new GuzzleHttpTimeFetcherClient( new HttpConfig( $timeServerHost2, $timeServerUrl2, headers: $timeServerHeaders2 ), new TimeapiIoTimeMapper() ), new DefaultTimeParametersMappers([ DefaultMappingFields::IPV4->value => 'ipAddress' ]), new DefaultMappingTimeParameters() ) ) ); var_dump((new TimeResolverService($apiTimeProvider2))->resolveTime()->now()); // ------------------------------------------------------------ // Example 3: Inline anonymous mapper for IP fetch response $ipServerHost3 = 'https://ifconfig.me'; $ipServerHeaders3 = [ 'User-Agent' => 'curl/7.64.1', 'Accept' => 'text/plain', ]; $timeServerHost3 = 'https://timeapi.io'; $timeServerUrl3 = '/api/time/current/ip'; $timeServerHeaders3 = ['Accept' => 'application/json']; $apiTimeProvider3 = new TimeResolverProvider( new GeoIpTimeApiResolver( new TimeApiFetcherService( new IpApiFetcher( new GuzzleHttpIpFetcherClient( new HttpConfig($ipServerHost3, headers: $ipServerHeaders3), new class implements HttpIpFetcherResponseMapperInterface { #[\Override] public function map(ResponseInterface $response): HttpIpFetcherResponseInterface { $body = $response->getBody(); $responseData = (string)$body; return new HttpIpFetcherResponse($responseData); } } ) ), new GuzzleHttpTimeFetcherClient( new HttpConfig( $timeServerHost3, $timeServerUrl3, headers: $timeServerHeaders3 ), new TimeapiIoTimeMapper() ), new DefaultTimeParametersMappers([ DefaultMappingFields::IPV4->value => 'ipAddress' ]), new DefaultMappingTimeParameters() ) ) ); var_dump((new TimeResolverService($apiTimeProvider3))->resolveTime()->now()); // ------------------------------------------------------------ // Example 4: Direct time fetch from IP-based service (premium key required) $timeServerHost4 = 'https://api.ipgeolocation.io'; $timeServerUrl4 = '/v2/ipgeo'; $timeServerParams4 = ['apiKey' => 'YOUR_API_KEY_HERE']; // Replace with your premium API key $apiTimeProvider4 = new TimeResolverProvider( new GeoIpTimeApiResolver( new HttpTimeFetcher( new GuzzleHttpTimeFetcherClient( new HttpConfig( $timeServerHost4, $timeServerUrl4, parameters: $timeServerParams4 ), new IpgeolocationIoTimeMapper() ) ) ) ); // Uncomment to test with valid API key: // var_dump((new TimeResolverService($apiTimeProvider4))->resolveTime()->now());
Notes
- Replace YOUR_API_KEY_HERE in Example 4 with your valid premium API key.
- The examples demonstrate flexibility in using different IP and time services.
- You can extend or customize mappers to fit different API response formats.
Running the example script
php ./examples/example.php