David Steinsland – informatikkstudent og webutvikler

Datoer i PHP – på den enkle måten

Å jobbe med datoer kan være riktig slitsomt til tider. Hvor mange ganger har du ikke klødd deg litt i bakhodet, og tenkt hvordan i huleste du kan formatere datoer som enten er formatert forskjellig, er fra ulike tidssoner eller som du må trekke fra / legge til dager/uker/måneder … ?

Ja, det har vært et problem. Med det mener jeg at løsningen er på plass, og at du kan slappe ekstra godt av. Dette innebærer selvfølgelig at du har en PHP-installasjon tilsvarende 5.3.x.

Alle dager i mars måned

Tidligere har vi måttet brukt PHPs datofunksjoner (date/strtotime/strftime …), men siden PHP 5.3 kan vi nemlig dra nytte av de nye DateTime-klassene og godene som medfølger.
Se bare hvor enkelt det er å skrive ut alle dagene i Mars 2011:

$march = new DateTime ('March 2011');

$days = new DatePeriod (
    $march,
    new DateInterval ('P1D'),
    $march->modify ('first day of next month')
);

foreach ($days as $day)
{
    echo $day->format ('Y-m-d'), "\n";
}

Årsaken til at jeg valgte å skrive «first day of next month» fremfor «last day of» er på grunn av at siste datoen blir ekskludert, som hadde betydd at 31. mars ikke hadde blitt skrevet ut.

I eksempelet mitt har jeg benyttet meg av alle klassene som inngår i DateTime-biblioteket (med unntak av DateTimeZone) hvor:

  • DateTime lager et objekt med 1. mars 2011 utifra «March 2011″
  • DatePeriod lager et objekt som inneholder alle datoer fra 1. mars til 1. april (eksklusivt) hvor det er 1 dag mellom hver instans (dette bestemmes av DateInterval)

Antall dager mellom to datoer

DateTime-klassen har et stort bruksområde, og kan for eksempel brukes til å finne differansen mellom to datoer:


$january = new Datetime ('January 2011');

$diff = $january->diff ( new DateTime ('April 2011') );

echo 'Difference between January and April: ',
$diff->format ('%R%a days');  // 90 days

%a fungerer slik at den skal gi meg det totale antallet dager mellom de to datoene. Denne funksjonaliteten fungerer dessverre ikke optimalt på Windows, og kan skape endel frustrasjoner. Men i lag med PHP 5.3 kan du også sammenligne to DateTime-instanser ved bruk av «comparison operators» (større/mindre enn, osv.) Dette gjør oss istand til å lage en «work-around» til Windows-problematikken:


$january = new DateTime ('January 2011');
$april = new DateTime ('April 2011');

// clone variable to keep $january clean..
$currdate = clone $january;

for ($days = 0; $currdate->modify ('+1 day') <= $april; ++$days);

echo "Difference between January and April: {$days} days";

Utvide DateTime med støtte for MySQL Datetime

Det er også ganske tilfredsstillende å benytte seg av DateTime ilag med MySQL DATETIME. I dette eksempelet har jeg valgt å utvide DateTime-klassen:

class MyDateTime extends DateTime
{
    const MYSQL = 'Y-m-d H:i:s';

    public static function createFromMySQL ($datetime)
    {
        return self::createFromFormat (self::MYSQL, $datetime);
    }
}

// date from MySQL
$date = MyDateTime::createFromMySQL ($row['my_date']);

$timestamp = $date->getTimestamp ();

echo "Date: {$date->format ('d.m.Y H:i')}\n";

Poenget mitt var ikke å utvide klassen for å legge til en enkel funksjon, men heller illustrere at det kan være lurt å gjøre det (DateTime-klassen har tross alt ikke tatt høyde for absolutt alt).
Kanskje det kunne vært en idé å gjøre Windows work-arounden min til en funksjon som utvider DateInterval ?

Som regel er det kun DateTime du har behov for i det daglige, men du kan også få god nytte av både DateInterval og DatePeriod om du for eksempel skal jobbe med kalendere.