/r/dailyprogramming #188 [Easy] - YYYY-MM-DD

Posted by Sander van Kasteel on November 13, 2014 · 874 words, 6 mins read

Al een tijdje volg ik op Reddit /r/dailyprogramming en het is een hartstikke leuke subreddit. 3 maal er per week (op maandag, woensdag en vrijdag) komen er programmeer uitdagingen online te staan en dit word mijn eerste keer dat ik zo’n uitdaging doe. Ik doe dit soort uitdagingen omdat ik graag een uitdaging aan ga.

Dit maal is de uitdaging, als volgt. We hebben een bedrijfsdatabase die gevuld is met wat datums. Alleen zijn die data in allerlei formaten en het is de bedoeling dat deze datums in standaard ISO 8601 formaat er uit komen rollen. Het formaat moet dus worden YYYY-MM-DD. De huidige datums staan in 1 van de volgende formaten;

  • yyyy-mm-dd
  • mm/dd/yy
  • mm#yy#dd
  • dd*mm*yyyy
  • (month word) dd, yy
  • (month word) dd, yyyy

We krijgen dus 1000 datums uit deze database en moeten dit dus maar in orde krijgen. Ik heb er voor gekozen om dit via een class te doen maar dat komt meer omdat het persoonlijke voorkeur is dan echt vanwege een technische keuze.

Mijn “algoritme” werkt op de volgende manier. Bij het instantiëren van het object hebben we 1 parameter, dat is namelijk de string die uit de database komt rollen. Vervolgens gaan we die string eens analyseren op basis van 1 van de volgende unieke kenmerken. Als er een streepje, slash, pound, of een ster teken in de string zit dan gaan we vervolgens een explode op dat unieke kenmerk doen en krijgen we daar de nodige array data uit. In sommige gevallen zoals bij een formaat waarbij een slash teken gebruikt is, hebben we een jaar getal wat bestaat uit 2 getallen en we moeten dit in omzetten naar een 4 tallig jaar getal. Daarvoor is de functie figureOutYear() bedoeld. Mocht het 2 tallig getal wat we hier in stoppen, groter zijn 50 en kleiner dan 99 dan betekent dat het een tussen 1900 en 2000 ligt, dus plakken we 19 voor het jaartal en anders plakken we 20 voor.

Daarnaast hebben we ook datums zoals Dec 26, 75” en “Mar 21, 1980”. Het unieke kenmerk is de spatie die tussen maand en dag zit en tussen dag en jaartal. Allereerst doen we een explode op die spatie. Daar krijgen we vervolgens een array uit met 3 elementen namelijk dag, maand en jaar. We zitten alleen met 1 klein probleempje, uit het element waar de dag in staat krijgen we namelijk de dag met een extra komma maar die komma werken we weg met de functie substr(). Daarna geven we het element waar het jaar in staat door de functie figureOutYear en daarna is het feest compleet. Dan kunnen we door de functie getDate() aanroepen om de correct geformatteerde datum terug te krijgen :)

Hieronder kan je de broncode vinden, mocht je geïnteresseerd zijn. Feedback geven mag altijd trouwens ;)

SOURCE :

<?php
/**
 * Created by PhpStorm.
 * User: Sander van Kasteel
 * Date: 11/13/14
 * Time: 8:35 PM
 */

class challenge188 {

    // Array for months with words
    private $dateWord = [
        'Jan' => '01',
        'Feb' => '02',
        'Mar' => '03',
        'Apr' => '04',
        'May' => '05',
        'Jun' => '06',
        'Jul' => '07',
        'Aug' => '08',
        'Sep' => '09',
        'Oct' => '10',
        'Nov' => '11',
        'Dec' => '12'
    ];

    private $year;
    private $month;
    private $day;

    // DAS uber overlord constructor!
    public function __construct($input)
    {
        // If this matches it means that the following scheme is used
        // yyyy-mm-dd
        if(preg_match("/-/", $input, $data) == "1")
        {
            $data = explode("-", $input);

            $this->day = $data[2];
            $this->month = $data[1];
            $this->year = $data[0];

        }

        // If this matches it means that the following scheme is used
        // mm/dd/yy
        if(preg_match("/\//", $input, $data) == "1")
        {
            $data = explode("/", $input);

            $this->day = $data[1];
            $this->month = $data[0];
            $this->year = $this->figureOutYear($data[2]);
        }

        // If this matches it means that the following scheme is used
        // mm#yy#dd
        if(preg_match("/#/", $input, $data) == "1")
        {
            $data = explode("#", $input);

            $this->day = $data[2];
            $this->month = $data[0];
            $this->year = $this->figureOutYear($data[1]);
        }

        // If this matches it means that the following scheme is used
        // dd*mm*yyyy
        if(preg_match("/\*/", $input, $data) == "1")
        {
            $data = explode("*", $input);

            $this->day = $data[0];
            $this->month = $data[1];
            $this->year = $data[2];
        }

        // If this matches it means that the following scheme is used
        // (month word) dd, yy OR(!!!!!) (month word) dd, yyyy
        if(preg_match("/ /", $input, $data) == "1")
        {
            $data = explode(" ", $input);

            $this->day = substr($data[1], 0, 2); // Cuts off the last comma sign on the end of the day
            $this->month = $this->figureOutMonth($data[0]);
            $this->year = $this->figureOutYear($data[2]);
        }

    }

    private function figureOutMonth($month)
    {
        foreach($this->dateWord as $key => $value)
        {
            if ($key == $month)
            {
                return $value;
            }
        }
    }

    private function figureOutYear($year)
    {
        // if the input $year has a length of 2 characters because years only go between 1950 - 2049
        // then we either add 19 or 20 to make it a complete YYYY format.
        if(strlen($year) == 2)
        {
           if ($year >= "50" && $year <= "99")
           {
               return "19" . $year;
           } elseif ($year >= "00" && $year <= "49") {
               return "20" . $year;
           }
        } else {
            // else the input $year is a fully fledged 4 number thingy!
            return $year;
        }
    }

    public function getDate()
    {
        return $this->year . "-" . $this->month . "-" . $this->day;
    }
}