Applies to: PHP 8.3 (8.3.33) and PHP 8.5 (8.5.4 on Ubuntu 26.04 LTS)
PHP’s date() uses the default timezone, which is UTC unless you set another one. Set it for one script with date_default_timezone_set('Asia/Kolkata');, or for every script with date.timezone = Asia/Kolkata in php.ini. To show one date in a different zone, use DateTime with a DateTimeZone. Always use a full identifier such as Europe/London, never an abbreviation such as IST.
1. Check the current timezone
php -r 'echo date_default_timezone_get(), " ", date("Y-m-d H:i:s T"), "\n";'
UTC 2026-09-30 06:28:13 UTC
According to the PHP manual, PHP picks the timezone in this order: a value set with date_default_timezone_set() in the script, then the date.timezone setting, then UTC. Since PHP 8.2 an empty or invalid date.timezone gives a warning instead of being silently ignored.
2. Set the timezone in a script
<?php
date_default_timezone_set('Asia/Kolkata');
echo date('Y-m-d H:i:s T P');
2026-09-30 11:58:13 IST +05:30
The format letters: T is the abbreviation (IST, BST, EST), P the offset from UTC, e the full identifier. Put the call at the top of the script, or in a file that every page includes, before any date is printed.
3. Set it for all scripts in php.ini
Find the file PHP loads:
$ php --ini Configuration File (php.ini) Path: "/etc/php/8.5/cli" Loaded Configuration File: "/etc/php/8.5/cli/php.ini"
In that file, the line is commented out by default (;date.timezone =). Remove the semicolon and add a zone:
date.timezone = Asia/Kolkata
On Ubuntu and Debian the command line and the web server read different files: /etc/php/8.5/cli/php.ini for scripts and cron jobs you run with php, and /etc/php/8.5/fpm/php.ini for websites served through PHP-FPM (use your PHP version in the path). Change both, then restart PHP-FPM with sudo systemctl restart php8.5-fpm. On cPanel hosting you change it in the MultiPHP INI Editor instead: see change the PHP timezone in cPanel.
A typo is easy to spot, because PHP falls back to UTC and says so:
PHP Warning: PHP Startup: Invalid date.timezone value 'IST', using 'UTC' instead in Unknown on line 0
4. Show a date in another timezone (DateTime)
For sites with users in several countries, keep the default at UTC, store times in UTC and convert only when you display them:
<?php
$meeting = new DateTimeImmutable('2026-12-01 09:30', new DateTimeZone('America/New_York'));
echo $meeting->format('Y-m-d H:i T'), "\n";
echo $meeting->setTimezone(new DateTimeZone('Asia/Kolkata'))->format('Y-m-d H:i T'), "\n";
echo $meeting->setTimezone(new DateTimeZone('UTC'))->format(DATE_ATOM), "\n";
2026-12-01 09:30 EST 2026-12-01 20:00 IST 2026-12-01T14:30:00+00:00
Identifiers follow daylight saving time for you: Europe/London printed BST for a July date and GMT for a January date.
5. Why you should not use abbreviations
date_default_timezone_set('IST') fails with Notice: date_default_timezone_set(): Timezone ID 'IST' is invalid and returns false. new DateTimeZone('IST') is worse, because it accepts abbreviations and gives no error:
IST => +02:00 Asia/Kolkata => +05:30
PHP read IST as a UTC+2 zone (timezone_name_from_abbr('IST') returns Asia/Jerusalem), not India Standard Time. EST is also a fixed -05:00 with no summer time. A misspelt identifier throws an exception (a DateInvalidTimeZoneException since PHP 8.3, a plain Exception before):
DateTimeZone::__construct(): Unknown or bad timezone (Europe/Londn)
6. List all PHP timezones
<?php $all = DateTimeZone::listIdentifiers(); // every current zone $asia = DateTimeZone::listIdentifiers(DateTimeZone::ASIA); // one region $india = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, 'IN'); // one country echo count($all), ' ', count($asia), "\n"; print_r($india);
419 82
Array
(
[0] => Asia/Kolkata
)
The regions are AFRICA, AMERICA, ANTARCTICA, ARCTIC, ASIA, ATLANTIC, AUSTRALIA, EUROPE, INDIAN, PACIFIC and UTC. timezone_identifiers_list() is the same function in procedural style. Old names such as Asia/Calcutta still work but are left out of the list; DateTimeZone::ALL_WITH_BC includes them. The count depends on the timezone database your PHP uses: timezone_version_get() returned 2026.1 in the official Docker image and 0.system on Ubuntu, which uses the system’s tzdata package.
A list like this is handy for a timezone drop-down in a user profile form: loop over $all and print one <option> per identifier.
The PHP timezone is separate from the server clock and from the database. To change the server’s own timezone, see set the time zone with timedatectl.
Official documentation: date_default_timezone_set(), DateTimeZone::listIdentifiers() and list of supported timezones.