Complete Guide to Working with Date and Time in Modern PHP

Complete Guide to Working with Date and Time in Modern PHP


Welcome to Kuasai Teknologi. In this article, we’ll discuss Working with Date and Time in Modern PHP. Handling dates and times is a crucial aspect of web application development, and PHP provides powerful modern tools for handling this.

Why Use DateTime Class?

Modern PHP (version 5.2+) provides the DateTime class which is far more powerful than old functions like date(), mktime(), or getdate(). The DateTime class offers:

  • Cleaner object-oriented interface
  • Better timezone handling
  • Easy date manipulation
  • Support for internationalization
  • Immutability with DateTimeImmutable

Basic DateTime Usage

Getting Current Date and Time

// Get current time
$now = new DateTime();
echo $now->format('Y-m-d H:i:s'); // 2025-04-10 15:30:45

// Using DateTimeImmutable (cannot be modified)
$nowImmutable = new DateTimeImmutable();

Creating Specific Dates

// Create specific date
$specificDate = new DateTime('2025-04-10');
$specificDate = new DateTime('2025-04-10 15:30:00');

// From format string
$dateFromString = DateTime::createFromFormat('d/m/Y', '10/04/2025');

Date Manipulation

$date = new DateTime('2025-04-10');

// Add time
$date->modify('+1 day');
$date->modify('+2 weeks');
$date->modify('+1 month');
$date->modify('+1 year');

// Subtract time
$date->modify('-1 week');

// Using DateInterval
$date->add(new DateInterval('P1D')); // +1 day
$date->sub(new DateInterval('P1W')); // -1 week

Date Comparison

$date1 = new DateTime('2025-04-10');
$date2 = new DateTime('2025-05-10');

if ($date1 < $date2) {
    echo 'Date 1 is earlier than date 2';
}

// Get difference
$interval = $date1->diff($date2);
echo $interval->days . ' days'; // 30 days
echo $interval->format('%y years, %m months, %d days');

Timezone Handling

Timezone is one of the most important aspects of date and time handling. PHP provides comprehensive timezone support.

// Set default timezone
date_default_timezone_set('Asia/Jakarta');

// Create DateTime with specific timezone
$dateJakarta = new DateTime('now', new DateTimeZone('Asia/Jakarta'));
$dateLondon = new DateTime('now', new DateTimeZone('Europe/London'));

// Change timezone
$date = new DateTime('2025-04-10 15:00:00', new DateTimeZone('Asia/Jakarta'));
$date->setTimezone(new DateTimeZone('UTC'));
echo $date->format('Y-m-d H:i:s'); // Convert to UTC

// Get all available timezones
$timezones = DateTimeZone::listIdentifiers();

Timezone Best Practices

  1. Always save dates in database in UTC
  2. Convert to user’s timezone when displaying
  3. Set default timezone in application configuration
  4. Use timezone identifiers (Asia/Jakarta), not offsets (+07:00)

DateTime Output Formatting

PHP provides various formats for date output:

$date = new DateTime('2025-04-10 15:30:00');

// Common formats
echo $date->format('Y-m-d H:i:s'); // 2025-04-10 15:30:00 (MySQL format)
echo $date->format('d/m/Y'); // 10/04/2025
echo $date->format('l, d F Y'); // Thursday, 10 April 2025

// ISO 8601 format
echo $date->format('c'); // 2025-04-10T15:30:00+00:00

// Unix timestamp format
echo $date->format('U'); // 1744291800

// Relative time format
echo $date->format('H:i'); // 15:30
echo $date->format('g:i A'); // 3:30 PM

Format Constants

// Using constants for standard formats
echo $date->format(DateTime::ATOM); // ISO 8601
echo $date->format(DateTime::RFC822); // RFC 822
echo $date->format(DateTime::COOKIE); // HTTP Cookie format
echo $date->format(DateTime::W3C); // W3C format

Carbon Library - Even More Powerful

Carbon is a library that extends the DateTime class with a more user-friendly API. Carbon is very popular in the PHP community.

Installing Carbon

composer require nesbot/carbon

Basic Carbon Usage

use Carbon\Carbon;

// Get current time
$now = Carbon::now();
$today = Carbon::today();
$tomorrow = Carbon::tomorrow();
$yesterday = Carbon::yesterday();

// Create specific date
$date = Carbon::create(2025, 4, 10, 15, 30, 0);
$date = Carbon::parse('2025-04-10 15:30:00');

// More intuitive manipulation
$date->addDay();
$date->subWeek();
$date->addMonths(2);
$date->subYears(1);

// Chainable methods
$futureDate = Carbon::now()
    ->addDays(5)
    ->addHours(2)
    ->subMinutes(30);

Carbon Features

// Comparison methods
$now = Carbon::now();

if ($now->isToday()) {
    echo 'Today';
}

if ($now->isWeekend()) {
    echo 'Weekend';
}

if ($now->isSameMonth(Carbon::parse('2025-04-01'))) {
    echo 'Same month';
}

// Start and End of period
$startOfMonth = Carbon::now()->startOfMonth();
$endOfMonth = Carbon::now()->endOfMonth();
$startOfWeek = Carbon::now()->startOfWeek();
$endOfWeek = Carbon::now()->endOfWeek();

// Diff for humans
echo Carbon::now()->diffForHumans(Carbon::now()->subDay()); // "1 day ago"
echo Carbon::now()->diffForHumans(Carbon::now()->addHour()); // "1 hour from now"

Database Integration

Saving Dates to Database

// Save in MySQL format (YYYY-MM-DD HH:MM:SS)
$date = new DateTime('now', new DateTimeZone('Asia/Jakarta'));
$mysqlDate = $date->format('Y-m-d H:i:s');

// Save in Unix timestamp
$timestamp = $date->format('U');

// Save in ISO 8601
$isoDate = $date->format(DateTime::ATOM);

Reading Dates from Database

// From MySQL format
$dbDate = '2025-04-10 15:30:00';
$date = DateTime::createFromFormat('Y-m-d H:i:s', $dbDate);

// From Unix timestamp
$timestamp = 1744291800;
$date = new DateTime("@$timestamp");

Best Practices

1. Always Use DateTime or Carbon

// ❌ DON'T use old functions
echo date('Y-m-d');

// âś… Use DateTime
echo (new DateTime())->format('Y-m-d');

// âś… Or Carbon
echo Carbon::now()->format('Y-m-d');

2. Handle Timezone Correctly

// Set default timezone at the start of application
date_default_timezone_set('Asia/Jakarta');

// Or use environment variable
date_default_timezone_set(getenv('APP_TIMEZONE') ?: 'UTC');

3. Validate Date Input

try {
    $date = new DateTime('invalid-date');
} catch (Exception $e) {
    echo 'Invalid date format: ' . $e->getMessage();
}

// Validate specific format
$date = DateTime::createFromFormat('d/m/Y', '10/04/2025');
if ($date === false) {
    echo 'Date format does not match';
}

4. Use DateTimeImmutable for Data That Shouldn’t Change

// DateTimeImmutable won't modify the original object
$date = new DateTimeImmutable('2025-04-10');
$newDate = $date->modify('+1 day');
// $date remains 2025-04-10
// $newDate is 2025-04-11

5. Error Handling

try {
    $date = new DateTime('invalid-date');
} catch (Exception $e) {
    // Log error
    error_log('Date error: ' . $e->getMessage());
    
    // Set default value
    $date = new DateTime('now');
}

Real-World Examples

Age Calculator

function calculateAge($birthDate) {
    $birth = new DateTime($birthDate);
    $today = new DateTime();
    $age = $today->diff($birth);
    return $age->y;
}

echo calculateAge('1990-05-15'); // 34 (as of 2025)

Business Days Calculator

function addBusinessDays($date, $days) {
    $current = new DateTime($date);
    $addedDays = 0;
    
    while ($addedDays < $days) {
        $current->modify('+1 day');
        if ($current->format('N') < 6) { // 1-5 are weekdays
            $addedDays++;
        }
    }
    
    return $current;
}

Date Range Generator

function getDateRange($startDate, $endDate) {
    $start = new DateTime($startDate);
    $end = new DateTime($endDate);
    $interval = new DateInterval('P1D');
    $dateRange = new DatePeriod($start, $interval, $end);
    
    foreach ($dateRange as $date) {
        echo $date->format('Y-m-d') . "\n";
    }
}

getDateRange('2025-04-01', '2025-04-10');

Testing with Dates

// Mock date for testing
use Carbon\Carbon;

// Set specific date for testing
Carbon::setTestNow(Carbon::create(2025, 4, 10));

// Now Carbon::now() will always return 2025-04-10
echo Carbon::now(); // 2025-04-10 00:00:00

// Reset after testing
Carbon::setTestNow();

Conclusion

Date and time handling in modern PHP has evolved far from old procedural functions. By using the DateTime class or libraries like Carbon, we can:

  • Handle timezones better
  • More intuitive date manipulation
  • More maintainable and testable code
  • Support for internationalization

Always use these modern tools in your PHP application development for more robust and reliable results.

Happy coding!