Reputation: 31
I am developing an application consisting of a web server using PHP and MySQL running on Windows that the user accesses through a web browser set to http://localhost
. But I want it to work in all United States time zones, including most of the State of Arizona that does not observe daylight saving time. To configure this script, I need to make PHP use the same time zone as Windows.
I have a PHP script that gets the timezone from command line on Windows. The results then need to be converted to the equivalent timezone in PHP's list.
Unfortunately I do not see a straightforward way to do this. Here is the script:
$comp_timezone = exec('systeminfo | findstr /C:"Time Zone"');
// results are: "Time Zone: (UTC-07:00) Arizona"
date_default_timezone_set($comp_timezone);
What I need to do is convert the string result from $comp_timezone
into something that the function date_default_timezone_set
can use, but as the above example demonstrates, Arizona does not exist as a timezone for php, the closest one would be America/Phoenix
.
So how do I convert a systeminfo
timezone to a PHP one?
Upvotes: 2
Views: 2352
Reputation: 368
Windows comes with its own list of time zones (for example: W. Europe Standard Time
).
PHP uses the IANA time zone database instead (it's also called tz database or even Olson database).
Unicode CLDR provides an XML file that allows mapping IANA names and Windows names. For example, see these XML element:
<!-- ... -->
<mapZone other="W. Europe Standard Time" territory="001" type="Europe/Berlin"/>
<mapZone other="W. Europe Standard Time" territory="AD" type="Europe/Andorra"/>
<!-- ... -->
As you can see, a Windows time zone name may correspond to more than one IANA time zone name.
I wrote a script that creates the PHP code representing two constants that allows resolving the names rather easily, parsing the above XML.
Here's for example an extract of such constants:
const WINDOWS_TO_PHP = [
// ...
'W. Europe Standard Time' => ['Europe/Andorra', 'Europe/Berlin', /*... */],
// ...
];
const PHP_TO_WINDOWS = [
// ...
'Europe/Andorra' => 'W. Europe Standard Time',
'Europe/Berlin' => 'W. Europe Standard Time',
// ...
];
By using those constants, you can retrieve the PHP time zone names simply by writing
$phpTimeZoneNames = WINDOWS_TO_PHP['W. Europe Standard Time'] ?? [];
And to retrieve the Windows time zone name starting from the PHP code name:
$windowsTimeZoneName = PHP_TO_WINDOWS['Europe/Andorra'] ?? '';
Upvotes: 0
Reputation: 99001
My solution is to loop DateTimeZone::listIdentifiers()
and try to find a match, i.e:.
$comp_timezone = exec('systeminfo | findstr /C:"Time Zone"');
//Time Zone: (UTC +01:00) Lisbon
//we match the last word of $comp_timezone
preg_match_all('/(\w+)$/', $comp_timezone, $rawTz, PREG_PATTERN_ORDER);
$rawTz = $rawTz[1][0]; //Lisbon
foreach (DateTimeZone::listIdentifiers() as $timezone) {
if(preg_match("/.*?\/$rawTz/", $timezone)){
echo $timezone;
//Europe/Lisbon
}
}
Notes:
America/Arizona
doesn't exist as a valid DateTimeZone
in PHP
.DateTimeZone
is only available on PHP 5 >= 5.2.0, PHP 7
Upvotes: 0
Reputation: 241798
A few things:
The systeminfo
command is just showing you the display name of the Windows time zone. You will need the identifier. You can use tzutil.exe /g
to return this - though that's still not going to help you here.
PHP uses IANA time zones, not Windows time zones. See the timezone tag wiki for more information about the two different types of time zones.
The translation between the two is handled by CLDR in this file.
For PHP, you can access CLDR data via the Internationalization Package. Enable this by adding (or uncommenting) to your php.ini
file:
extension=php_intl.dll
Then you can simply call the following function to return the local time zone as an IANA identifier. (Internally, it relies on ICU and CLDR to translate.)
IntlTimeZone::createDefault()->getID()
This will return "America/Phoenix"
in your example. You can then use it with any of PHP's normal time zone functions, including date_default_timezone_set
if you wish.
Even though you can do this, think carefully about whether or not you really should do this. In most cases, relying on the system's local time zone setting from a web application (or any server-side application) is an anti-pattern. It's far too easy for the time zone to change. It's a global setting which doesn't usually require any administrator rights. It's also problematic if your data is not UTC based and you then try to migrate it from one server to another. In the vast majority of cases, it's better to think about time zone at the application logic level, not system-wide or application-wide, and the time zone of the server hosting your code should usually be considered irrelevant.
Upvotes: 6