Ankündigung

Einklappen
Keine Ankündigung bisher.

DateTime in DatePeriod effizienter finden

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • DateTime in DatePeriod effizienter finden

    Es wurden einige Klassen erstellt, damit iCalendar-Dateien geparsed und erstellt werden können. Diese iCalendar-Dateien können per Google-Calendar, iCal oder auch Outlook erstellt und abonniert, damit man andere Personen über z.B. Veranstaltungen informieren kann.

    Klassen wurden erstellt und die Grundfunktionen sind schon enthalten. Zum testen habe ich mir den Inhalt Deutsche Feiertage als iCalendar-Datei geholt um Tests durchzuführen.

    Ausschnitt aus der iCalendar-Datei:

    Code:
    BEGIN:VCALENDAR
    VERSION:2.0
    BEGIN:VEVENT
    UID:DE-IF-1225
    DTSTART;VALUE=DATE:20101225
    DTEND;VALUE=DATE:20101226
    RRULE:FREQ=YEARLY;INTERVAL=1
    SUMMARY:1. Weihnachtsfeiertag
    DTSTAMP:20100101T000000Z
    END:VEVENT
    END:VCALENDAR
    Für die restliche Frage gehe ich der einfachheit halber von folgender Struktur aus, die ein Event aus dem Kalender darstellt. Hier ist jeweils Anfangs- (from), und Endzeit (until) angegeben, sowie eine Wiederholung (Interval).

    PHP-Code:
    $event = array(
        
    'summary' => '1. Weihnachtsfeiertag',
        
    'from' => new DateTime('2010-12-25'),
        
    'until' => new DateTime('2010-12-26'),
        
    'interval' => new DateInterval('P1Y')
    ); 
    Nun habe ich gesehen, dass in der Datei nicht für jedes Jahr ein neues Eintrag für in diesem Fall dem 1. Weihnachtsfeiertag eingetragen wurde, sondern ein Interval, wie oft sich dieser wiederholt.

    Ich eine Funktion isActive erstellt um einen Status zu erhalten ob dieser Event gerade stattfindet. Hierzu muss ich jedoch (in diesem Fall noch sehr geringe Menge) die Elemente aus dem DatePeriod mit foreach durchlaufen.

    1. Frage:
    Wie begrenzt man die Durchläufe der DatePeriod sinnvoll? Reicht es eurer Meinung nach per LimitIterator einen Ausschnitt der DatePeriod zu holen oder gibt es hier bei umfangreicheren DatePeriod effizientere Möglichkeiten? (Beispiel: DatePeriod von 1900 bis 2100, ich möchte aber nur Einträge von 2010 bis 2020).

    2. Frage:
    Gibt es bei einer DatePeriod eine einfachere Möglichkeit zu erkennen ob sich ein Datum in einem Eintrag der DatePeriod befindet?


    Der Beispielcode:

    PHP-Code:
    $event = array(
        
    'summary' => '1. Weihnachtsfeiertag',
        
    'from' => new DateTime('2010-12-25'),
        
    'until' => new DateTime('2010-12-26'),
        
    'interval' => new DateInterval('P1Y')
    );

    function 
    between($needle$from$until) {
        if(
    $needle $from) {
            return 
    false;
        }
        if(
    $needle $until) {
            return 
    false;
        }
        return 
    true;
    }

    function 
    getIterator($event) {
        
    $fromPeriod = new DatePeriod($event['from'], $event['interval'], 10);
        
    $untilPeriod = new DatePeriod($event['until'], $event['interval'], 10);
        
        
    $iterator = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);
        
    $iterator->attachIterator(new IteratorIterator($fromPeriod), 'from');
        
    $iterator->attachIterator(new IteratorIterator($untilPeriod), 'until');
        return 
    $iterator;
    }

    function 
    isActive($event$currentDateTime) {
        foreach(
    getIterator($event) as $item) {
            if(
    between($currentDateTime$item['from'], $item['until'])) {
                return 
    true;
            }
        }
        return 
    false;
    }

    var_dump(isActive($event, new DateTime()));
    var_dump(isActive($event, new DateTime('2014-12-25 13:37'))); 
    PHP-Code:
    bool(false)
    bool(true


  • #2
    Ist vielleicht nicht sonderlich generisch, aber man könnte bestimmte Standardfälle einfach abbilden, indem man für 'P1Y' das Jahr im Datumsstring weglässt austauscht, für 'P1M' Jahr und Monat etc. Bei Wochen o.ä. wirds dann schwieriger.
    --

    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


    --

    Kommentar


    • #3
      Im ersten Beispiel habe ich noch fest auf 10 Elemente beschränkt, dies ist keine gute Lösung, darum verwende ich jetzt das zu prüfende Datum als Enddatum in der Period.

      PHP-Code:
      $from = new DateTime('2000-12-25');
      $interval = new DateInterval('P1Y');

      $dateTime = new DateTime('2014-12-25');
      $until $dateTime;

      $period = new DatePeriod($from$interval$until);
      foreach(
      $period as $item) {
          
      var_dump($item->format('Y-m-d H:i:s'));
          if(
      $item->format('Y-m-d') == $dateTime->format('Y-m-d')) {
              
      var_dump(true);
          }

      Es werden folgende Elemente aus der $period geprüft.

      PHP-Code:
      string(19"2000-12-25 00:00:00"
      string(19"2001-12-25 00:00:00"
      string(19"2002-12-25 00:00:00"
      string(19"2003-12-25 00:00:00"
      string(19"2004-12-25 00:00:00"
      string(19"2005-12-25 00:00:00"
      string(19"2006-12-25 00:00:00"
      string(19"2007-12-25 00:00:00"
      string(19"2008-12-25 00:00:00"
      string(19"2009-12-25 00:00:00"
      string(19"2010-12-25 00:00:00"
      string(19"2011-12-25 00:00:00"
      string(19"2012-12-25 00:00:00"
      string(19"2013-12-25 00:00:00" 
      Wie zu sehen, wird kein true ausgegeben, da das Enddatum nicht mit geprüft wird. Also noch zum Enddatum einmal den Interval hinzufügen.

      PHP-Code:
      $from = new DateTime('2000-12-25');
      $interval = new DateInterval('P1Y');

      $dateTime = new DateTime('2014-12-25');
      $until = clone $dateTime;
      $until->add($interval);

      $period = new DatePeriod($from$interval$until);
      foreach(
      $period as $item) {
          
      var_dump($item->format('Y-m-d H:i:s'));
          if(
      $item->format('Y-m-d') == $dateTime->format('Y-m-d')) {
              
      var_dump(true);
          }

      Jetzt funktioniert das schon besser, da auch das zu prüfende Datum ein true zurückgegeben wird.

      PHP-Code:
      string(19"2000-12-25 00:00:00"
      string(19"2001-12-25 00:00:00"
      string(19"2002-12-25 00:00:00"
      string(19"2003-12-25 00:00:00"
      string(19"2004-12-25 00:00:00"
      string(19"2005-12-25 00:00:00"
      string(19"2006-12-25 00:00:00"
      string(19"2007-12-25 00:00:00"
      string(19"2008-12-25 00:00:00"
      string(19"2009-12-25 00:00:00"
      string(19"2010-12-25 00:00:00"
      string(19"2011-12-25 00:00:00"
      string(19"2012-12-25 00:00:00"
      string(19"2013-12-25 00:00:00"
      string(19"2014-12-25 00:00:00"
      bool(true
      Wenn sich nun aber schon das Enddatum nach dem zu prüfenden Eintrag befindet, z.B. wenn eine Zeit angegeben wurde, so wird ein Eintrag zuviel geprüft. Hier nehme ich mal an, dass ein Eintrag zuviel geprüft nicht weiter schlimm ist und sich auch nicht merkbar negativ auf die Performance aus auswirken sollte.

      PHP-Code:
      $from = new DateTime('2000-12-25');
      $interval = new DateInterval('P1Y');

      $dateTime = new DateTime('2014-12-25 13:37');
      $until = clone $dateTime;
      $until->add($interval);

      $period = new DatePeriod($from$interval$until);
      foreach(
      $period as $item) {
          
      var_dump($item->format('Y-m-d H:i:s'));
          if(
      $item->format('Y-m-d') == $dateTime->format('Y-m-d')) {
              
      var_dump(true);
          }

      PHP-Code:
      string(19"2000-12-25 00:00:00"
      string(19"2001-12-25 00:00:00"
      string(19"2002-12-25 00:00:00"
      string(19"2003-12-25 00:00:00"
      string(19"2004-12-25 00:00:00"
      string(19"2005-12-25 00:00:00"
      string(19"2006-12-25 00:00:00"
      string(19"2007-12-25 00:00:00"
      string(19"2008-12-25 00:00:00"
      string(19"2009-12-25 00:00:00"
      string(19"2010-12-25 00:00:00"
      string(19"2011-12-25 00:00:00"
      string(19"2012-12-25 00:00:00"
      string(19"2013-12-25 00:00:00"
      string(19"2014-12-25 00:00:00"
      bool(true)
      string(19"2015-12-25 00:00:00" 
      Ich glaube das ist schon eine funktionierende und brauchbare Lösung. Aktuell habe ich keine Idee wie man das deutlich verbessern könnte. Jedoch bin ich vor Vorschläge offen.

      Kommentar

      Lädt...
      X