PHP
MySQL
date format
convert date
programming tutorial

convert php date to mysql format

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Converting a date from user-facing PHP input into a MySQL-safe value is routine in forms, imports, and API handlers. The hard part is not formatting, it is handling ambiguous input and timezone assumptions consistently. A robust solution parses strictly, validates early, and writes only normalized values to the database.

Understand the Target MySQL Column

Before you write conversion logic, confirm the database column type. DATE stores only a calendar date, while DATETIME stores date and time without timezone conversion. TIMESTAMP may convert between session timezone and UTC depending on server settings.

That difference affects application behavior. If a billing due date should never shift by timezone, DATE is usually the right model. If an event happened at a precise moment, use DATETIME or TIMESTAMP with explicit timezone rules in your app and migration scripts.

A practical mapping strategy:

  • User birthday or due date maps to DATE in Y-m-d format.
  • User-entered local appointment time maps to DATETIME after explicit local parsing.
  • Audit event time maps to UTC, then stored in DATETIME or TIMESTAMP by team convention.

Parse Input Strictly With DateTimeImmutable

Avoid substring slicing and permissive parsing shortcuts. DateTimeImmutable::createFromFormat gives control over accepted format and keeps parsing deterministic.

php
1<?php
2
3declare(strict_types=1);
4
5function toMysqlDate(string $input, string $inputFormat = 'd/m/Y'): string
6{
7    $dt = DateTimeImmutable::createFromFormat($inputFormat, $input);
8    $errors = DateTimeImmutable::getLastErrors();
9
10    if (!$dt || $errors['warning_count'] > 0 || $errors['error_count'] > 0) {
11        throw new InvalidArgumentException("Invalid date: {$input}");
12    }
13
14    return $dt->format('Y-m-d');
15}
16
17echo toMysqlDate('04/03/2026');

The strict error check matters. Without it, invalid values can sometimes parse into unexpected dates.

Convert Local Date Time to UTC Before Storing

If input contains local time, parse in source timezone and convert once to UTC. That avoids daylight-saving surprises and keeps cross-region queries consistent.

php
1<?php
2
3declare(strict_types=1);
4
5function toMysqlUtcDateTime(
6    string $input,
7    string $inputFormat,
8    string $sourceTimezone
9): string {
10    $sourceTz = new DateTimeZone($sourceTimezone);
11    $utcTz = new DateTimeZone('UTC');
12
13    $local = DateTimeImmutable::createFromFormat($inputFormat, $input, $sourceTz);
14    $errors = DateTimeImmutable::getLastErrors();
15
16    if (!$local || $errors['warning_count'] > 0 || $errors['error_count'] > 0) {
17        throw new InvalidArgumentException("Invalid datetime: {$input}");
18    }
19
20    return $local->setTimezone($utcTz)->format('Y-m-d H:i:s');
21}
22
23echo toMysqlUtcDateTime('2026-03-04 09:30', 'Y-m-d H:i', 'America/Toronto');

This keeps conversion policy explicit and testable.

Write to MySQL With Prepared Statements

Formatting correctly is only half the job. Always use prepared statements so date values are bound as parameters, not string-concatenated into SQL.

php
1<?php
2
3declare(strict_types=1);
4
5$pdo = new PDO(
6    'mysql:host=localhost;dbname=app;charset=utf8mb4',
7    'user',
8    'pass',
9    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
10);
11
12$dueDate = toMysqlDate('28/03/2026', 'd/m/Y');
13
14$stmt = $pdo->prepare('INSERT INTO invoices (due_date) VALUES (:due_date)');
15$stmt->execute([':due_date' => $dueDate]);

Using a single helper for parse and normalize logic reduces duplication across controllers and CLI scripts.

Handle Nullable Inputs and Imports

In real systems, some date fields are optional. Decide once whether blank input becomes NULL or triggers validation failure.

php
1<?php
2
3declare(strict_types=1);
4
5function toNullableMysqlDate(?string $input, string $inputFormat = 'd/m/Y'): ?string
6{
7    if ($input === null || trim($input) === '') {
8        return null;
9    }
10
11    return toMysqlDate($input, $inputFormat);
12}

For CSV imports, process row by row and collect row-level errors. That allows partial success and clear feedback about which lines failed and why.

Testing Conversion Behavior

Date bugs often appear around month boundaries and daylight-saving changes. Add tests for:

  • Leap day and non-leap year boundaries.
  • Invalid day and month combinations.
  • Local times around timezone offset changes.
  • Empty or whitespace input when nullable fields are allowed.

A small test matrix catches more production issues than adding another parser branch later.

Common Pitfalls

  • Using strtotime for strict business input formats, which can parse unexpected values.
  • Ignoring parse warnings from createFromFormat and accepting malformed input.
  • Storing local date time without recording or converting timezone context.
  • Building SQL with concatenated date strings instead of prepared statements.
  • Mixing rules for DATE and DATETIME in one helper without explicit intent.

Summary

  • Define conversion rules based on target MySQL column semantics first.
  • Parse with DateTimeImmutable::createFromFormat and enforce strict error checks.
  • Convert local date time to UTC explicitly when moment accuracy matters.
  • Insert normalized values through prepared statements.
  • Treat nullability and import error handling as part of the conversion contract.

Course illustration
Course illustration

All Rights Reserved.