1. php
  2. /references
  3. /datetime-functions

Date and Time Functions Reference

Introduction to PHP Date and Time

PHP provides extensive support for date and time manipulation through built-in functions and the DateTime class. This reference covers both procedural functions and object-oriented approaches to working with dates and times.

Basic Date and Time Functions

date() - Format a Date

<?php
// Current date and time
echo date('Y-m-d H:i:s'); // Output: 2023-01-15 14:30:25

// Various formats
echo date('d/m/Y'); // Output: 15/01/2023
echo date('F j, Y'); // Output: January 15, 2023
echo date('l, F j, Y'); // Output: Sunday, January 15, 2023
echo date('g:i A'); // Output: 2:30 PM

// Format specific timestamp
$timestamp = 1642262400;
echo date('Y-m-d', $timestamp); // Output: 2022-01-15

// Common format patterns
$formats = [
    'Y-m-d' => '2023-01-15',
    'Y-m-d H:i:s' => '2023-01-15 14:30:25',
    'd/m/Y' => '15/01/2023',
    'F j, Y' => 'January 15, 2023',
    'M j, Y' => 'Jan 15, 2023',
    'l, F j, Y' => 'Sunday, January 15, 2023',
    'D, M j, Y' => 'Sun, Jan 15, 2023',
    'g:i A' => '2:30 PM',
    'H:i:s' => '14:30:25',
    'c' => '2023-01-15T14:30:25+00:00', // ISO 8601
    'r' => 'Sun, 15 Jan 2023 14:30:25 +0000', // RFC 2822
    'U' => '1673794225' // Unix timestamp
];

foreach ($formats as $format => $example) {
    echo "$format: " . date($format) . "\n";
}
?>

time() and mktime() - Get Timestamps

<?php
// Current Unix timestamp
$now = time();
echo $now; // Output: 1673794225

// Create timestamp from date components
$timestamp = mktime(14, 30, 25, 1, 15, 2023); // hour, minute, second, month, day, year
echo date('Y-m-d H:i:s', $timestamp); // Output: 2023-01-15 14:30:25

// First day of current month
$firstDay = mktime(0, 0, 0, date('n'), 1, date('Y'));
echo date('Y-m-d', $firstDay);

// Last day of current month
$lastDay = mktime(0, 0, 0, date('n') + 1, 0, date('Y'));
echo date('Y-m-d', $lastDay);

// Calculate age
function calculateAge($birthDate) {
    $birth = strtotime($birthDate);
    $today = time();
    $age = floor(($today - $birth) / (365.25 * 24 * 3600));
    return $age;
}

echo calculateAge('1990-05-15'); // Output: 32 (approximately)

// Days until next birthday
function daysUntilBirthday($birthDate) {
    $birth = DateTime::createFromFormat('Y-m-d', $birthDate);
    $today = new DateTime();
    
    $nextBirthday = clone $birth;
    $nextBirthday->setDate($today->format('Y'), $birth->format('m'), $birth->format('d'));
    
    if ($nextBirthday < $today) {
        $nextBirthday->modify('+1 year');
    }
    
    return $today->diff($nextBirthday)->days;
}

echo daysUntilBirthday('1990-05-15');
?>

DateTime Class

Creating DateTime Objects

<?php
// Create DateTime objects
$now = new DateTime();
echo $now->format('Y-m-d H:i:s');

// From string
$date1 = new DateTime('2023-01-15');
$date2 = new DateTime('2023-01-15 14:30:25');
$date3 = new DateTime('next Monday');
$date4 = new DateTime('+1 week');

// From format
$date5 = DateTime::createFromFormat('d/m/Y', '15/01/2023');
$date6 = DateTime::createFromFormat('Y-m-d H:i:s', '2023-01-15 14:30:25');

// From timestamp
$date7 = new DateTime('@1673794225');

// With timezone
$date8 = new DateTime('2023-01-15 14:30:25', new DateTimeZone('America/New_York'));

// Current date in different timezone
$utc = new DateTime('now', new DateTimeZone('UTC'));
$ny = new DateTime('now', new DateTimeZone('America/New_York'));
$tokyo = new DateTime('now', new DateTimeZone('Asia/Tokyo'));

echo "UTC: " . $utc->format('Y-m-d H:i:s T') . "\n";
echo "New York: " . $ny->format('Y-m-d H:i:s T') . "\n";
echo "Tokyo: " . $tokyo->format('Y-m-d H:i:s T') . "\n";

// Error handling
try {
    $invalidDate = new DateTime('invalid date');
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}
?>

DateTime Manipulation

<?php
$date = new DateTime('2023-01-15 14:30:25');

// Add time
$date->add(new DateInterval('P1D')); // Add 1 day
echo $date->format('Y-m-d H:i:s'); // Output: 2023-01-16 14:30:25

$date->add(new DateInterval('PT2H30M')); // Add 2 hours 30 minutes
echo $date->format('Y-m-d H:i:s'); // Output: 2023-01-16 17:00:25

// Subtract time
$date->sub(new DateInterval('P1W')); // Subtract 1 week
echo $date->format('Y-m-d H:i:s'); // Output: 2023-01-09 17:00:25

// Modify with string
$date = new DateTime('2023-01-15');
$date->modify('+1 day');
$date->modify('+2 hours');
$date->modify('next Monday');
$date->modify('last day of this month');

// Set specific values
$date->setDate(2023, 12, 25);
$date->setTime(10, 30, 0);

// Clone for immutable operations
$originalDate = new DateTime('2023-01-15');
$modifiedDate = clone $originalDate;
$modifiedDate->add(new DateInterval('P1D'));

echo "Original: " . $originalDate->format('Y-m-d') . "\n";
echo "Modified: " . $modifiedDate->format('Y-m-d') . "\n";

// DateTimeImmutable (PHP 5.5+)
$immutableDate = new DateTimeImmutable('2023-01-15');
$newDate = $immutableDate->add(new DateInterval('P1D'));

echo "Immutable: " . $immutableDate->format('Y-m-d') . "\n";
echo "New: " . $newDate->format('Y-m-d') . "\n";
?>

Date Intervals and Periods

<?php
// Create intervals
$interval1 = new DateInterval('P1Y2M3DT4H5M6S'); // 1 year, 2 months, 3 days, 4 hours, 5 minutes, 6 seconds
$interval2 = DateInterval::createFromDateString('1 day 2 hours');

// Calculate difference between dates
$date1 = new DateTime('2023-01-15');
$date2 = new DateTime('2023-02-20');
$diff = $date1->diff($date2);

echo $diff->format('%R%a days'); // Output: +36 days
echo $diff->format('%y years, %m months, %d days'); // Output: 0 years, 1 months, 5 days

// Properties of DateInterval
echo "Years: " . $diff->y . "\n";
echo "Months: " . $diff->m . "\n";
echo "Days: " . $diff->d . "\n";
echo "Hours: " . $diff->h . "\n";
echo "Minutes: " . $diff->i . "\n";
echo "Seconds: " . $diff->s . "\n";
echo "Total days: " . $diff->days . "\n";
echo "Inverted: " . ($diff->invert ? 'Yes' : 'No') . "\n";

// Date periods
$start = new DateTime('2023-01-01');
$interval = new DateInterval('P1D');
$end = new DateTime('2023-01-10');

$period = new DatePeriod($start, $interval, $end);

foreach ($period as $date) {
    echo $date->format('Y-m-d') . "\n";
}

// Working days between two dates
function getWorkingDays(DateTime $start, DateTime $end) {
    $workingDays = 0;
    $period = new DatePeriod($start, new DateInterval('P1D'), $end);
    
    foreach ($period as $date) {
        $dayOfWeek = $date->format('N'); // 1 (Monday) to 7 (Sunday)
        if ($dayOfWeek < 6) { // Monday to Friday
            $workingDays++;
        }
    }
    
    return $workingDays;
}

$start = new DateTime('2023-01-01');
$end = new DateTime('2023-01-31');
echo "Working days: " . getWorkingDays($start, $end);
?>

Timezone Handling

Working with Timezones

<?php
// Get available timezones
$timezones = DateTimeZone::listIdentifiers();
echo "Total timezones: " . count($timezones) . "\n";

// Timezone by region
$americaTimezones = DateTimeZone::listIdentifiers(DateTimeZone::AMERICA);
$europeTimezones = DateTimeZone::listIdentifiers(DateTimeZone::EUROPE);

// Create timezone objects
$utc = new DateTimeZone('UTC');
$newYork = new DateTimeZone('America/New_York');
$london = new DateTimeZone('Europe/London');
$tokyo = new DateTimeZone('Asia/Tokyo');

// Convert between timezones
$date = new DateTime('2023-01-15 12:00:00', $utc);
echo "UTC: " . $date->format('Y-m-d H:i:s T') . "\n";

$date->setTimezone($newYork);
echo "New York: " . $date->format('Y-m-d H:i:s T') . "\n";

$date->setTimezone($london);
echo "London: " . $date->format('Y-m-d H:i:s T') . "\n";

$date->setTimezone($tokyo);
echo "Tokyo: " . $date->format('Y-m-d H:i:s T') . "\n";

// Timezone information
$tz = new DateTimeZone('America/New_York');
$transitions = $tz->getTransitions();
$location = $tz->getLocation();

echo "Timezone: " . $tz->getName() . "\n";
echo "Country: " . $location['country_code'] . "\n";
echo "Latitude: " . $location['latitude'] . "\n";
echo "Longitude: " . $location['longitude'] . "\n";

// DST transitions
$now = new DateTime();
$offset = $tz->getOffset($now);
echo "Current offset: " . ($offset / 3600) . " hours\n";

// Time zone abbreviations
echo "EST offset: " . timezone_offset_get(timezone_open('EST'), $now) / 3600 . " hours\n";

// Default timezone
date_default_timezone_set('America/New_York');
echo "Default timezone: " . date_default_timezone_get() . "\n";
echo "Current time: " . date('Y-m-d H:i:s T') . "\n";
?>

Timezone Conversion Utilities

<?php
class TimezoneConverter
{
    public static function convertTime($time, $fromTz, $toTz)
    {
        $date = new DateTime($time, new DateTimeZone($fromTz));
        $date->setTimezone(new DateTimeZone($toTz));
        return $date;
    }
    
    public static function getTimezoneOffset($timezone, $baseTimezone = 'UTC')
    {
        $base = new DateTime('now', new DateTimeZone($baseTimezone));
        $target = new DateTime('now', new DateTimeZone($timezone));
        
        return $base->getOffset() - $target->getOffset();
    }
    
    public static function getCurrentTimeInTimezone($timezone)
    {
        return new DateTime('now', new DateTimeZone($timezone));
    }
    
    public static function getTimezonesByOffset($offset)
    {
        $timezones = [];
        $now = new DateTime();
        
        foreach (DateTimeZone::listIdentifiers() as $timezone) {
            $tz = new DateTimeZone($timezone);
            if ($tz->getOffset($now) === $offset * 3600) {
                $timezones[] = $timezone;
            }
        }
        
        return $timezones;
    }
}

// Usage examples
$converted = TimezoneConverter::convertTime('2023-01-15 12:00:00', 'UTC', 'America/New_York');
echo $converted->format('Y-m-d H:i:s T') . "\n";

$offset = TimezoneConverter::getTimezoneOffset('America/New_York');
echo "New York offset from UTC: " . ($offset / 3600) . " hours\n";

$currentNY = TimezoneConverter::getCurrentTimeInTimezone('America/New_York');
echo "Current time in NY: " . $currentNY->format('Y-m-d H:i:s T') . "\n";

$gmt5Timezones = TimezoneConverter::getTimezonesByOffset(-5);
print_r(array_slice($gmt5Timezones, 0, 5));
?>

Date Formatting and Parsing

Custom Formatting

<?php
// Custom date formatter class
class DateFormatter
{
    private static $customFormats = [
        'short' => 'M j, Y',
        'medium' => 'F j, Y',
        'long' => 'l, F j, Y',
        'iso' => 'Y-m-d',
        'rfc' => 'r',
        'timestamp' => 'U'
    ];
    
    public static function format($date, $format)
    {
        if (!$date instanceof DateTime) {
            $date = new DateTime($date);
        }
        
        $formatString = self::$customFormats[$format] ?? $format;
        return $date->format($formatString);
    }
    
    public static function relative($date)
    {
        if (!$date instanceof DateTime) {
            $date = new DateTime($date);
        }
        
        $now = new DateTime();
        $diff = $now->diff($date);
        
        if ($diff->y > 0) {
            return $diff->y . ' year' . ($diff->y > 1 ? 's' : '') . ' ago';
        } elseif ($diff->m > 0) {
            return $diff->m . ' month' . ($diff->m > 1 ? 's' : '') . ' ago';
        } elseif ($diff->d > 0) {
            return $diff->d . ' day' . ($diff->d > 1 ? 's' : '') . ' ago';
        } elseif ($diff->h > 0) {
            return $diff->h . ' hour' . ($diff->h > 1 ? 's' : '') . ' ago';
        } elseif ($diff->i > 0) {
            return $diff->i . ' minute' . ($diff->i > 1 ? 's' : '') . ' ago';
        } else {
            return 'just now';
        }
    }
    
    public static function humanReadable($date)
    {
        if (!$date instanceof DateTime) {
            $date = new DateTime($date);
        }
        
        $now = new DateTime();
        $diff = $now->diff($date);
        
        if ($diff->days === 0) {
            return 'today';
        } elseif ($diff->days === 1 && $diff->invert) {
            return 'yesterday';
        } elseif ($diff->days === 1 && !$diff->invert) {
            return 'tomorrow';
        } elseif ($diff->days < 7 && $diff->invert) {
            return $date->format('l'); // Day name
        } else {
            return $date->format('M j');
        }
    }
}

// Usage
$date = new DateTime('2023-01-15');
echo DateFormatter::format($date, 'short') . "\n";
echo DateFormatter::format($date, 'medium') . "\n";
echo DateFormatter::format($date, 'long') . "\n";

$pastDate = new DateTime('-2 hours');
echo DateFormatter::relative($pastDate) . "\n";

$yesterday = new DateTime('-1 day');
echo DateFormatter::humanReadable($yesterday) . "\n";
?>

Parsing Different Date Formats

<?php
class DateParser
{
    private static $formats = [
        'Y-m-d',
        'd/m/Y',
        'm/d/Y',
        'd-m-Y',
        'm-d-Y',
        'Y-m-d H:i:s',
        'd/m/Y H:i:s',
        'F j, Y',
        'M j, Y',
        'j F Y',
        'j M Y'
    ];
    
    public static function parse($dateString)
    {
        // Try each format until one works
        foreach (self::$formats as $format) {
            $date = DateTime::createFromFormat($format, $dateString);
            if ($date !== false) {
                return $date;
            }
        }
        
        // Try strtotime as fallback
        $timestamp = strtotime($dateString);
        if ($timestamp !== false) {
            return new DateTime("@$timestamp");
        }
        
        throw new InvalidArgumentException("Could not parse date: $dateString");
    }
    
    public static function parseMultiple(array $dateStrings)
    {
        $dates = [];
        foreach ($dateStrings as $dateString) {
            try {
                $dates[] = self::parse($dateString);
            } catch (InvalidArgumentException $e) {
                $dates[] = null;
            }
        }
        return $dates;
    }
    
    public static function validateDate($dateString, $format = 'Y-m-d')
    {
        $date = DateTime::createFromFormat($format, $dateString);
        return $date && $date->format($format) === $dateString;
    }
}

// Usage
$dates = [
    '2023-01-15',
    '15/01/2023',
    'January 15, 2023',
    'Jan 15, 2023',
    'next Monday',
    '+1 week'
];

foreach ($dates as $dateString) {
    try {
        $parsed = DateParser::parse($dateString);
        echo "$dateString -> " . $parsed->format('Y-m-d') . "\n";
    } catch (Exception $e) {
        echo "$dateString -> Error: " . $e->getMessage() . "\n";
    }
}

// Validation
$validDates = ['2023-01-15', '2023-02-30', '2023-13-01'];
foreach ($validDates as $date) {
    $isValid = DateParser::validateDate($date);
    echo "$date: " . ($isValid ? 'Valid' : 'Invalid') . "\n";
}
?>

Date Calculations and Utilities

Common Date Calculations

<?php
class DateCalculations
{
    public static function getQuarter(DateTime $date)
    {
        $month = (int) $date->format('n');
        return ceil($month / 3);
    }
    
    public static function getWeekOfYear(DateTime $date)
    {
        return (int) $date->format('W');
    }
    
    public static function getDayOfYear(DateTime $date)
    {
        return (int) $date->format('z') + 1;
    }
    
    public static function isWeekend(DateTime $date)
    {
        $dayOfWeek = (int) $date->format('N');
        return $dayOfWeek >= 6; // Saturday or Sunday
    }
    
    public static function isLeapYear($year)
    {
        return (bool) date('L', mktime(0, 0, 0, 1, 1, $year));
    }
    
    public static function getDaysInMonth($month, $year)
    {
        return (int) date('t', mktime(0, 0, 0, $month, 1, $year));
    }
    
    public static function getFirstDayOfMonth(DateTime $date)
    {
        return new DateTime($date->format('Y-m-01'));
    }
    
    public static function getLastDayOfMonth(DateTime $date)
    {
        return new DateTime($date->format('Y-m-t'));
    }
    
    public static function getNextWorkday(DateTime $date)
    {
        $nextDay = clone $date;
        $nextDay->add(new DateInterval('P1D'));
        
        while (self::isWeekend($nextDay)) {
            $nextDay->add(new DateInterval('P1D'));
        }
        
        return $nextDay;
    }
    
    public static function getPreviousWorkday(DateTime $date)
    {
        $prevDay = clone $date;
        $prevDay->sub(new DateInterval('P1D'));
        
        while (self::isWeekend($prevDay)) {
            $prevDay->sub(new DateInterval('P1D'));
        }
        
        return $prevDay;
    }
    
    public static function getWorkdaysBetween(DateTime $start, DateTime $end)
    {
        $workdays = 0;
        $current = clone $start;
        
        while ($current <= $end) {
            if (!self::isWeekend($current)) {
                $workdays++;
            }
            $current->add(new DateInterval('P1D'));
        }
        
        return $workdays;
    }
    
    public static function addWorkdays(DateTime $date, $days)
    {
        $result = clone $date;
        $addedDays = 0;
        
        while ($addedDays < $days) {
            $result->add(new DateInterval('P1D'));
            if (!self::isWeekend($result)) {
                $addedDays++;
            }
        }
        
        return $result;
    }
}

// Usage examples
$date = new DateTime('2023-01-15');

echo "Quarter: " . DateCalculations::getQuarter($date) . "\n";
echo "Week of year: " . DateCalculations::getWeekOfYear($date) . "\n";
echo "Day of year: " . DateCalculations::getDayOfYear($date) . "\n";
echo "Is weekend: " . (DateCalculations::isWeekend($date) ? 'Yes' : 'No') . "\n";
echo "Is leap year: " . (DateCalculations::isLeapYear(2023) ? 'Yes' : 'No') . "\n";
echo "Days in month: " . DateCalculations::getDaysInMonth(1, 2023) . "\n";

$firstDay = DateCalculations::getFirstDayOfMonth($date);
echo "First day of month: " . $firstDay->format('Y-m-d') . "\n";

$lastDay = DateCalculations::getLastDayOfMonth($date);
echo "Last day of month: " . $lastDay->format('Y-m-d') . "\n";

$nextWorkday = DateCalculations::getNextWorkday($date);
echo "Next workday: " . $nextWorkday->format('Y-m-d') . "\n";

$start = new DateTime('2023-01-01');
$end = new DateTime('2023-01-31');
$workdays = DateCalculations::getWorkdaysBetween($start, $end);
echo "Workdays in January 2023: $workdays\n";

$futureWorkday = DateCalculations::addWorkdays($date, 10);
echo "10 workdays from now: " . $futureWorkday->format('Y-m-d') . "\n";
?>

Age and Duration Calculations

<?php
class AgeCalculator
{
    public static function getExactAge(DateTime $birthDate, DateTime $currentDate = null)
    {
        if ($currentDate === null) {
            $currentDate = new DateTime();
        }
        
        $diff = $birthDate->diff($currentDate);
        
        return [
            'years' => $diff->y,
            'months' => $diff->m,
            'days' => $diff->d,
            'total_days' => $diff->days,
            'hours' => $diff->h,
            'minutes' => $diff->i,
            'seconds' => $diff->s
        ];
    }
    
    public static function getAgeInYears(DateTime $birthDate, DateTime $currentDate = null)
    {
        if ($currentDate === null) {
            $currentDate = new DateTime();
        }
        
        return $birthDate->diff($currentDate)->y;
    }
    
    public static function getAgeInDays(DateTime $birthDate, DateTime $currentDate = null)
    {
        if ($currentDate === null) {
            $currentDate = new DateTime();
        }
        
        return $birthDate->diff($currentDate)->days;
    }
    
    public static function formatDuration(DateInterval $interval)
    {
        $parts = [];
        
        if ($interval->y > 0) {
            $parts[] = $interval->y . ' year' . ($interval->y > 1 ? 's' : '');
        }
        if ($interval->m > 0) {
            $parts[] = $interval->m . ' month' . ($interval->m > 1 ? 's' : '');
        }
        if ($interval->d > 0) {
            $parts[] = $interval->d . ' day' . ($interval->d > 1 ? 's' : '');
        }
        if ($interval->h > 0) {
            $parts[] = $interval->h . ' hour' . ($interval->h > 1 ? 's' : '');
        }
        if ($interval->i > 0) {
            $parts[] = $interval->i . ' minute' . ($interval->i > 1 ? 's' : '');
        }
        if ($interval->s > 0) {
            $parts[] = $interval->s . ' second' . ($interval->s > 1 ? 's' : '');
        }
        
        if (empty($parts)) {
            return '0 seconds';
        }
        
        if (count($parts) === 1) {
            return $parts[0];
        }
        
        $last = array_pop($parts);
        return implode(', ', $parts) . ' and ' . $last;
    }
    
    public static function getLifetimeStatistics(DateTime $birthDate)
    {
        $now = new DateTime();
        $age = self::getExactAge($birthDate, $now);
        
        return [
            'age_in_years' => $age['years'],
            'age_in_months' => ($age['years'] * 12) + $age['months'],
            'age_in_days' => $age['total_days'],
            'age_in_hours' => $age['total_days'] * 24,
            'age_in_minutes' => $age['total_days'] * 24 * 60,
            'age_in_seconds' => $age['total_days'] * 24 * 60 * 60,
            'next_birthday' => self::getNextBirthday($birthDate),
            'days_until_birthday' => self::getDaysUntilBirthday($birthDate)
        ];
    }
    
    private static function getNextBirthday(DateTime $birthDate)
    {
        $today = new DateTime();
        $nextBirthday = new DateTime($today->format('Y') . '-' . $birthDate->format('m-d'));
        
        if ($nextBirthday < $today) {
            $nextBirthday->add(new DateInterval('P1Y'));
        }
        
        return $nextBirthday;
    }
    
    private static function getDaysUntilBirthday(DateTime $birthDate)
    {
        $nextBirthday = self::getNextBirthday($birthDate);
        $today = new DateTime();
        
        return $today->diff($nextBirthday)->days;
    }
}

// Usage
$birthDate = new DateTime('1990-05-15');
$exactAge = AgeCalculator::getExactAge($birthDate);
echo "Exact age: " . AgeCalculator::formatDuration($birthDate->diff(new DateTime())) . "\n";

$ageInYears = AgeCalculator::getAgeInYears($birthDate);
echo "Age in years: $ageInYears\n";

$ageInDays = AgeCalculator::getAgeInDays($birthDate);
echo "Age in days: $ageInDays\n";

$stats = AgeCalculator::getLifetimeStatistics($birthDate);
print_r($stats);
?>

This comprehensive reference covers the essential date and time functions and classes in PHP, providing practical examples for real-world development scenarios.