Analogt ur der viser tid
← Tilbage til GuidesMellem

PHP DateTime

Komplet guide til dato-håndtering i PHP — fra date() til DateTimeImmutable og tidszoner.

Foto: Hugo Barbosa / Unsplash

Tre måder at arbejde med datoer i PHP

PHP har tre primære værktøjer til datoer: de procedurale funktioner date(), strtotime() og time(), samt de objektorienterede klasser DateTime og DateTimeImmutable.

I moderne PHP-kode er DateTimeImmutable standardvalget. Den forhindrer utilsigtede ændringer af eksisterende dato-objekter, hvilket er en hyppig kilde til fejl med den mutable DateTime-klasse. Procedurale funktioner som date() bruges stadig til hurtig formatering af aktuelle tidsstempler.

date() — Hurtig formatering

date() formaterer et timestamp efter et format-string. Hvis du ikke angiver et timestamp, bruges det aktuelle tidspunkt.

<?php
// Aktuel dato og tid
echo date('Y-m-d H:i:s');     // 2026-05-03 20:45:12
echo date('d/m/Y');           // 03/05/2026
echo date('l, j. F Y');       // Sunday, 3. May 2026

// Med specifikt timestamp
$timestamp = 1735689600;       // 1. januar 2025
echo date('d-m-Y', $timestamp); // 01-01-2025

// strtotime parser tekst til timestamp
$next = strtotime('+2 weeks');
echo date('d-m-Y', $next);

$payday = strtotime('last friday of this month');
echo date('d-m-Y', $payday);

De vigtigste format-tegn: Y (år, 4 cifre), m (måned, 01-12), d (dag, 01-31), H (time, 00-23), i (minut), s (sekund).

DateTimeImmutable — Det moderne valg

DateTimeImmutable returnerer et nyt objekt ved hver modifikation. Det gør koden forudsigelig og forhindrer subtile bugs hvor en delt reference ændres uventet.

<?php
// Opret fra string
$start = new DateTimeImmutable('2026-05-03 14:30:00');

// Opret fra format
$birthday = DateTimeImmutable::createFromFormat(
    'd/m/Y',
    '15/03/1989'
);

// Modify returnerer NYT objekt
$nextWeek = $start->modify('+1 week');
$endOfMonth = $start->modify('last day of this month');

// Originalen er uændret
echo $start->format('Y-m-d');     // 2026-05-03
echo $nextWeek->format('Y-m-d');  // 2026-05-10

// Sætterne returnerer også nye objekter
$morning = $start
    ->setTime(8, 0, 0)
    ->setDate(2026, 6, 1);

echo $morning->format('Y-m-d H:i'); // 2026-06-01 08:00

Brug aldrig DateTime (mutable) til værdier der kan deles eller passes rundt. DateTimeImmutable er sikrere som default.

Tidszoner og DateTimeZone

Datoer uden tidszone er en almindelig kilde til fejl. Sæt altid en eksplicit tidszone — enten globalt eller per objekt.

<?php
// Global tidszone (typisk i bootstrap)
date_default_timezone_set('Europe/Copenhagen');

// Per objekt
$copenhagen = new DateTimeImmutable(
    'now',
    new DateTimeZone('Europe/Copenhagen')
);

$utc = $copenhagen->setTimezone(new DateTimeZone('UTC'));

echo $copenhagen->format('H:i T'); // 14:30 CEST
echo $utc->format('H:i T');        // 12:30 UTC

// Konvertér mellem tidszoner
$tokyo = new DateTimeZone('Asia/Tokyo');
$meeting = $copenhagen->setTimezone($tokyo);

echo $meeting->format('Y-m-d H:i T');

// Hent alle gyldige tidszoner
$europeZones = DateTimeZone::listIdentifiers(
    DateTimeZone::EUROPE
);

Gem altid datoer i databasen som UTC. Konvertér først til brugerens lokale tidszone ved visning. Det gør sommertid og internationalisering meget lettere.

Datoberegninger med DateInterval

DateInterval repræsenterer en periode — eksempelvis 2 dage og 3 timer. Brug den til addition, subtraktion og difference mellem datoer.

<?php
$now = new DateTimeImmutable();

// ISO 8601 duration format
$twoWeeks = new DateInterval('P2W');
$threeMonths = new DateInterval('P3M');
$twoHours = new DateInterval('PT2H');

$deadline = $now->add($twoWeeks);
$earlier = $now->sub($twoHours);

// Beregn forskel mellem to datoer
$start = new DateTimeImmutable('2026-01-01');
$end = new DateTimeImmutable('2026-05-03');

$diff = $start->diff($end);
echo $diff->days;         // 122 (totale dage)
echo $diff->m;            // 4 (måneder)
echo $diff->format(
    '%y år, %m måneder, %d dage'
);

// DatePeriod til at iterere
$period = new DatePeriod(
    $start,
    new DateInterval('P1D'),
    $end
);

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

Praktiske eksempler

Beregn alder fra fødselsdato

<?php
function calculateAge(string $birthdate): int {
    $birth = new DateTimeImmutable($birthdate);
    $today = new DateTimeImmutable();
    return $today->diff($birth)->y;
}

echo calculateAge('1989-03-15'); // 37

Næste arbejdsdag

<?php
function nextWorkday(DateTimeImmutable $from): DateTimeImmutable {
    $next = $from->modify('+1 day');

    while (in_array($next->format('N'), ['6', '7'])) {
        $next = $next->modify('+1 day');
    }

    return $next;
}

$today = new DateTimeImmutable();
echo nextWorkday($today)->format('l Y-m-d');

Formatering på dansk

<?php
// IntlDateFormatter til lokaliseret output
$fmt = new IntlDateFormatter(
    'da_DK',
    IntlDateFormatter::FULL,
    IntlDateFormatter::NONE
);

$date = new DateTimeImmutable('2026-05-03');
echo $fmt->format($date);
// "søndag den 3. maj 2026"

// Eller manuel danske månedsnavne
$months = [
    1 => 'januar', 'februar', 'marts', 'april', 'maj',
    'juni', 'juli', 'august', 'september',
    'oktober', 'november', 'december',
];

$d = new DateTimeImmutable('2026-05-03');
echo $d->format('j') . '. ' . $months[(int)$d->format('n')];
// "3. maj"

Best Practices

+Brug DateTimeImmutable som default - undgå mutable DateTime medmindre du har en specifik grund
+Sæt altid en eksplicit tidszone via DateTimeZone, stol ikke på serverens default
+Gem datoer i databasen som UTC, konvertér til lokal tidszone ved visning
+Brug ISO 8601-format (Y-m-d H:i:s) i database og API responses for konsistens
+Brug IntlDateFormatter til lokaliserede dato-strings i stedet for manuelle oversættelser
+Validér dato-input fra brugere med createFromFormat() og tjek for false return
+Sammenlign DateTimeImmutable-objekter direkte med <, >, == operatorer