Hassan Agmir Hassan Agmir

PHP Date Format

Hassan Agmir
PHP Date Format

PHP’s built-in date() function is a powerful tool for formatting dates and time, but its real potential becomes clear when you start exploring advanced use cases. In this post, we’ll cover:

  1. The basics recap
  2. Advanced format characters
  3. Combining formats for locale-aware output
  4. Relative/conditional formatting
  5. Timezone handling
  6. Custom date formatting via DateTime
  7. Performance considerations
  8. Best practices and pitfalls

1. Quick Recap: The Fundamentals

echo date('Y-m-d H:i:s'); // 2025-06-22 14:45:03
  • Y – 4-digit year
  • y – 2-digit year
  • m – 2-digit month
  • n – month (1–12) without leading zero
  • d – 2-digit day of month
  • j – day without leading zero
  • H – 24‑hr hour
  • h – 12‑hr hour
  • i – minutes
  • s – seconds

These basics are well-known. But PHP supports dozens more format specifiers. Let’s explore some advanced options.

2. Advanced Format Characters

2.1 Day, Week, and Year info

  • D – Three-letter weekday (Mon, Tue)
  • l (lowercase ‘L’) – Full weekday (Monday, Tuesday)
  • N – ISO weekday as number (1 = Monday…7 = Sunday)
  • w – Numeric weekday (0 = Sunday…6 = Saturday)
  • z – Day of year starting from 0
  • W – ISO week number (weeks starting Monday, week 1 has Jan 4)
echo date('l, \t\h\\e jS \o\f F Y') . "\n";
// Example: "Sunday, the 22nd of June 2025"
echo date('W') . "\n";        // ISO week number (e.g., "25")
echo date('z') . "\n";        // Day of year zero-indexed (e.g., "173")

2.2 Month/Quarter Info

  • F – Full month text (January–December)
  • M – Short month text (Jan–Dec)
  • n – Numeric month without leading zeros (1–12)
  • t – Number of days in current month
echo date('F') . "\n";       // "June"
echo date('t') . "\n";       // "30"

2.3 Time and Timezone Info

  • a, A – am/pm
  • g, G – 12‑hr/24‑hr format without leading zeros
  • U – Unix timestamp
  • e, T – Timezone identifier / abbreviation
  • O, P, Z – UTC offset formats and offset in seconds
echo date('g:ia T') . "\n";   // e.g. "2:45pm UTC"
echo date('P') . "\n";        // e.g. "+00:00"
echo date('Z') . "\n";        // "0" (offset secs)
echo time() . "\n";           // Current timestamp, same as U
echo date('r') . "\n";        // RFC 2822 date: "Sun, 22 Jun 2025 14:45:03 +0000"

2.4 Escape Sequences

To literally output characters like S or j, prefix with backslash:

echo date('\T\o\d\a\y \i\s l') . "\n"; 
// "Today is Sunday"

3. Combining Formats for Localization

While PHP’s date() offers robust formatting, it’s not locale-aware (always English). Combine with strftime() or IntlDateFormatter for other languages:

setlocale(LC_TIME, 'fr_FR.UTF-8');
echo strftime('%A %e %B %Y, %H:%M') . "\n";
// "dimanche 22 juin 2025, 14:45"

With Intl:

$fmt = new IntlDateFormatter(
    'fr_FR',
    IntlDateFormatter::FULL,
    IntlDateFormatter::SHORT,
    'Europe/Paris',
    IntlDateFormatter::GREGORIAN
);
echo $fmt->format(new DateTime());

3.1 Date in Words

echo strftime('%d %b %Y') . "\n";  // 22 Jun 2025 (fr_FR -> "22 juin 2025")

4. Relative/Conditional Formatting

Dynamic formatting based on how "old" a date is:

function human_diff(DateTime $dt, DateTime $now = null) {
    $now = $now ?: new DateTime('now', $dt->getTimezone());
    $diff = $now->diff($dt);
    
    if ($diff->y) return $diff->y . ' year' . ($diff->y>1?'s':'') . ' ago';
    if ($diff->m) return $diff->m . ' month' . ($diff->m>1?'s':'') . ' ago';
    if ($diff->d) return $diff->d . ' day' . ($diff->d>1?'s':'') . ' ago';
    if ($diff->h) return $diff->h . ' hour' . ($diff->h>1?'s':'') . ' ago';
    if ($diff->i) return $diff->i . ' minute' . ($diff->i>1?'s':'') . ' ago';
    return 'just now';
}

echo human_diff(new DateTime('-3 hours')); // "3 hours ago"

Add today/yesterday/tomorrow text:

function smart_date(DateTime $dt) { /* logic with midnight and date comparison */}

5. Timezone Handling

Be explicit:

$date = new DateTime('2025-06-22 14:45:03', new DateTimeZone('UTC'));
$date->setTimezone(new DateTimeZone('America/New_York'));
echo $date->format('Y-m-d H:i T'); // "2025-06-22 10:45 EDT"

Parse with PHP’s DateTime::createFromFormat():

$date = DateTime::createFromFormat('d/m/Y H:i:s', '31/12/2025 23:59:59');
echo $date->format('Y-m-d H:i:s');

6. Custom Formats with DateTime

DateTimeInterface + format():

$dt = new DateTime('2025-06-22T14:45:03+02:00');
// RFC 3339:
echo $dt->format(DateTime::RFC3339) . "\n";
// ISO8601:
echo $dt->format(DateTime::ISO8601) . "\n";
// Atom:
echo $dt->format(DateTime::ATOM) . "\n";

Add microseconds:

$now = DateTime::createFromFormat('U.u', microtime(true));
echo $now->format('Y-m-d H:i:s.u'); // 2025-06-22 14:45:03.123456

Custom relative format with conditionals:

$parts = [];
if ($diff->h) $parts[] = $diff->h . 'h';
if ($diff->i) $parts[] = $diff->i . 'm';
echo implode('', $parts);

7. Performance Tips

  • Reuse DateTimeZone objects
  • Avoid date() and strtotime() repeatedly in loops
  • Microbenchmarks:
$start = microtime(true);
for ($i=0; $i<1e5; $i++) {
    DateTime::createFromFormat('U', time());
}
echo (microtime(true) - $start);

date() is faster but less flexible.

8. Best Practices & Pitfalls

  1. Never assume server timezone – set date_default_timezone_set() or use DateTimeZone.
  2. Avoid strtotime() with ambiguous strings – be specific.
  3. Use ISO 8601 or RFC3339 when storing dates.
  4. Escape carefully.
  5. Be locale-aware if internationalization is required.

9. Advanced Recipes

9.1 Next N occurrence:

function nextByWeekday($weekday, $timezone='UTC') {
    $ts = strtotime("next $weekday");
    return date('Y-m-d', $ts);
}

9.2 Is it a leap year?

function isLeap($year=null) {
    $year = $year ?: date('Y');
    return ((($year % 4 == 0) && ($year %100 != 0)) || ($year % 400 == 0));
}

9.3 Quarter:

function getQuarter(DateTime $d){
  return ceil((int)$d->format('n')/3);
}

9.4 Business days between dates:

function businessDays($from, $to) {
    $start = new DateTime($from);
    $end   = new DateTime($to);
    $count = 0;
    while ($start <= $end) {
       $w = $start->format('N');
       if ($w < 6) $count++;
       $start->modify('+1 day');
    }
    return $count;
}

Conclusion 

  • PHP’s date() function is just the tip of the iceberg.
  • Combine with DateTime, IntlDateFormatter, and smart functions for powerful date logic.
  • Handy recipes for business days, quarters, and smart relative labels.
  • Always mind timezone, performance, and localization.
Subscribe to my Newsletters

Stay updated with the latest programming tips, tricks, and IT insights! Join my community to receive exclusive content on coding best practices.

© Copyright 2025 by Hassan Agmir . Built with ❤ by Me