Introduction: Why Time is a Pain
\n\nImagine: you are writing an online store. A client from New York places an order at 15:00 local time. You save the date to the database. Then the server, located in Moscow, decides the order was made at 22:00. And chaos ensues: delivery is late, reports don't match, clients get angry.
\n\nFamiliar situation? Welcome to the world of time zones in PHP. This topic is a real quest for beginners and even experienced developers. But there's good news: if you figure it out once and set everything up correctly, you will forget about date headaches forever.
\n\nIn this article, we will break down how to work with time zones in PHP, how to avoid pitfalls with daylight saving time, and why UTC is your best friend. Let's go!
\n\nGlobal Time Zone Setting in PHP
\n\nThe very first step is to make sure PHP knows which time zone your server is working in. This is done via the date.timezone directive in php.ini or directly in code using the date_default_timezone_set() function.
// Set the time zone for the entire script\ndate_default_timezone_set('Europe/Moscow');\n\necho date('Y-m-d H:i:s'); // Will output current Moscow time\n\nBut attention! If you are working with users from different countries, fixing one zone for the entire project is a bad idea. It's better to always store time in UTC (Coordinated Universal Time) and convert it for the specific user.
\n\nChecking the Current Time Zone
\n\nIt's always useful to know which zone is set right now:
\n\necho date_default_timezone_get(); // For example: 'Europe/Moscow'\n\nThe DateTimeZone Object — Your Main Tool
\n\nPHP has a powerful DateTimeZone object. It allows you to work with time zones as independent entities. Let's look at a basic example:
\n\n$timezone = new DateTimeZone('America/New_York');\n$datetime = new DateTime('now', $timezone);\n\necho $datetime->format('Y-m-d H:i:s'); // Current time in New York\n\nNotice: we passed the time zone directly into the DateTime constructor. This is the cleanest way to work with time zones in PHP.
List of All Available Time Zones
\n\nWant to know which zones PHP supports? Call the listIdentifiers() method:
$zones = DateTimeZone::listIdentifiers();\necho count($zones); // Around 400+ zones!\n\n// Print the first 10\nprint_r(array_slice($zones, 0, 10));\n\nThis list is huge. But you don't need to memorize all of them — it's enough to know standard identifiers like Europe/London, Asia/Tokyo, or UTC.
Conversion Between Time Zones
\n\nThe most common task: take a time in one zone and convert it to another. In PHP, this is done elegantly using the setTimezone() method.
// Time in UTC\n$utcTime = new DateTime('2025-03-15 12:00:00', new DateTimeZone('UTC'));\n\n// Convert to Tokyo\n$tokyoTime = clone $utcTime;\n$tokyoTime->setTimezone(new DateTimeZone('Asia/Tokyo'));\n\necho $utcTime->format('Y-m-d H:i:s') . ' UTC'; // 2025-03-15 12:00:00 UTC\necho ' = ';\necho $tokyoTime->format('Y-m-d H:i:s') . ' Tokyo'; // 2025-03-15 21:00:00 Tokyo\n\nNotice: we used clone to avoid modifying the original object. If you don't do this, the original time will also "move" to Tokyo.
Best Practice: Store Everything in UTC
\n\nThe golden rule of web development: always store dates and times in UTC. Database, cache, logs — everywhere UTC. And only convert for the user at the output stage.
\n\n// Save to DB (approximately)\n$nowUTC = new DateTime('now', new DateTimeZone('UTC'));\n$db->query("INSERT INTO or