Dude: Zeitraum bei Array: Anfang und Ende finden?

hi leute,

ich habe ein array
Array
(
    [0] => 2006-12-02
    [1] => 2006-12-03
    [2] => 2006-12-04
    [3] => 2006-12-05
    [4] => 2006-12-16
    [5] => 2006-12-17
    [6] => 2006-12-18
)

und eine variable
$bericht = "2006-12-03"

ich will nun das anfangs- und enddatum des zeitraums haben.

Das wäre hier:
    [0] => 2006-12-02
...
    [3] => 2006-12-05

Wie komme ich zu diesem Ergebnis?

Vielen Dank
dude

Folgender Versuch:

position von dem gesuchtem im array zu finden
$gesuchtedatum="2006-12-03";
$pos;
for($i=0;$i<count($array);$i++){
if($gesuchtedatum==$array[$i]){$pos=$i; break;}
}

schleife von dem gefundener stelle nach unten laufen, so lange der datumswert sich nur in ein Tag abweicht.
$start="";
$laufdatum=$gesuchtedatum;
$tag=1;
for($i=$pos-1;$i>=0;$i--){
if(date("Y-m-d",strtotime($laufdatum." -".($tag++)." days"))==$array[$i]){
$laufdatum=$array[$i];
}else{
$start=$i+1;
break;
}
}

und das selbe nach oben laufen lassen.
$ende="";
$laufdatum=$gesuchtedatum;
$tag=1;
for($i=$pos+1;$i<count($array);$i++){
if(date("Y-m-d",strtotime($laufdatum." +".($tag++)." days"))==$array[$i]){
$laufdatum=$array[$i];
}else{
$ende=$i-1;
break;
}
}

Fehlerhaftes Ergebnis:

die ergebnisse:        $pos      $array[$start]    $array[$ende]
    [0] => 2006-12-01  "0"        ""                "2006-12-02"
    [1] => 2006-12-02  "1"        ""                "2006-12-03"
    [2] => 2006-12-03  "2"        "2006-12-02"      "2006-12-04"
    [3] => 2006-12-04  "3"        "2006-12-03"      "2006-12-04"

  1. Moin!

    schleife von dem gefundener stelle nach unten laufen, so lange der datumswert sich nur in ein Tag abweicht.
    $start="";
    $laufdatum=$gesuchtedatum;
    $tag=1;
    for($i=$pos-1;$i>=0;$i--){

    hier vergleichst Du $laufdatum, was gleich ist mit $gesuchtedatum mit $array[$i]. Aber Du ziehst vorher von $laufdatum was ab. Und zwar die Anzahl der Tage, die Du mitzählst. Anschließend setzt Du $laufdatum aber auf $arry[$i] und ziehst im nächsten Durchlauf wieder $tage ab, also doppelt soviel wie nötig.

    Lass Dir einfach mal das errechnete date ausgeben und schau selbst.

    if(date("Y-m-d",strtotime($laufdatum." -".($tag++)." days"))==$array[$i]){
    $laufdatum=$array[$i];
    }else{
    $start=$i+1;
    break;
    }
    }

    Ich kann kein PHP, nehme aber mal an, daß Dir dies eher hilft:

    [code lang=php]
    $start="";
    $tag=0;
    for( $i=$pos-1; $i>=0; $i--) {
        if( date("Y-m-d",strtotime($gesuchtedatum." +".(--$tag)." days"))==$array[$i]){
            $start=$i;
        }
        else {
            break;
        }
    }

    Nebenbei: Wenn Dein Array groß ist, aber sortiert, dann solte Dir für die erste Schleife eine binäre suche schneller einen Treffer finden.

    Wenn Du aber lieber, wie jetzt, linear suchst, dann kannst Du das $start auch gleich bei der Suche nach dem gewünschten Datum finden. Einfach zusätzlich schauen, ob die Differenz vom Datum im aktuellen Element um mehr als 1 vom vorherigen abweicht und in dem Fall $start auf den aktuellen Index setzen.

    -- Skeeve

    1. $start="";
      $tag=0;
      for( $i=$pos-1; $i>=0; $i--) {
          if( date("Y-m-d",strtotime($gesuchtedatum." +".(--$tag)." days"))==$array[$i]){
              $start=$i;
          }
          else {
              break;
          }
      }

      Hi Skeeve,

      leider klappt Dein Code gar nicht. Ich habe weiter herumgespielt:

      $pos;
         for($i=0;$i<count($ugschicht);$i++){
         if($dat==$ugschicht[$i]){$pos=$i; break;}
         }
         echo $pos;

      $start="";
         $laufdatum=$dat;
         $tag=1;
         for($i=$pos-1;$i>=0;$i--){
         if(date("Y-m-d",strtotime($laufdatum." -".($tag++)." days"))==$ugschicht[$i]){
         //$laufdatum=$ugschicht[$i];
         $start=$i;
         }else{
         $start=$i+1;
         break;
         }
         }

      $ende="";
         $laufdatum=$dat;
         $tag=1;
         for($i=$pos+1;$i<count($ugschicht);$i++){
         if(date("Y-m-d",strtotime($laufdatum." +".($tag++)." days"))==$ugschicht[$i]){
         //$laufdatum=$ugschicht[$i];
         $ende=$i;
         }else{
         $ende=$i-1;
         break;
         }
         }

      Problem ist nun, dass bei ugschicht[0] keine Augabe erfolgt. Der Beginn des zweiten Zeitraums in diesem Monat wird fehlerlos ausgegeben.

      Ebenso problematisch verhält es sich mit dem Ende bei dem letzten Arryeintrag.

      Nur: WARUM?!

      Dude

      1. Moin!

        leider klappt Dein Code gar nicht.

        Ich *liebe* die Fehlerbeschreibung "klappt nicht". Geht es vielleicht etwas weniger wortkarg? Gibt es einen Syntax Terror oder was heißt "klappt nicht"? Ich gehe übrigens davon aus, daß eventuelle Syntaxfehler von Dir korrigiert werden, da ich (wie gesagt) kein php beherrsche. Darum habe ich mir auch Dein neues Experiment nicht angetan. ;-)

        -- Skeeve

      2. Moin!

        Ich habe meinen Algorithmus jetzt mal in perl implementiert, allerdings nicht mit Datumswerten sondern mit Integern. Um das Prinzip zu zeigen, sollte das ja reichen.

          
        my @array=( 1..5, 9..20, 24..30 ); # stellt Deine Daten dar  
          
        for my $gesuchtedatum (1..31) { # Damit teste ich einfach mal alle Daten  
          
         printf "%2d: ", $gesuchtedatum;  
          
         my $pos= undef;  
         my $i=0;  
         foreach my $laufdatum (@array) {  
          if ($gesuchtedatum == $laufdatum) {  
           $pos= $i;  
           last; # <- break;  
          }  
          ++$i;  
         }  
          
         if ( not defined $pos ) {  
          print "keine Daten\n";  
          next; # <- continue;  
         }  
          
         # hier eine kleine Änderung des Original Algorithmus  
         # Ich setze den Start und später das Ende auf  
         # die gefundene Position.  
         my $start= $pos;  
         my $tag= 0;  
         for( my $i= $start-1; $i>=0; --$i) {  
          if( $gesuchtedatum+(--$tag) == $array[$i] ) {  
           $start=$i;  
          }  
          else {  
           last; # <- break;  
          }  
         }  
          
         my $ende= $pos;  
         my $tag= 0;  
         for( my $i= $ende+1; $i<=$#array; ++$i) {  
          if( $gesuchtedatum+(++$tag) == $array[$i] ) {  
           $ende=$i;  
          }  
          else {  
           last; # <- break;  
          }  
         }  
          
         printf "Bereich %2d - %2d\n",$array[$start],$array[$ende];  
        }  
        
        

        Ich muß sagen: Das klappt wunderprächtig. Hier die Ausgabe:

        1: Bereich  1 -  5
         2: Bereich  1 -  5
         3: Bereich  1 -  5
         4: Bereich  1 -  5
         5: Bereich  1 -  5
         6: keine Daten
         7: keine Daten
         8: keine Daten
         9: Bereich  9 - 20
        10: Bereich  9 - 20
        11: Bereich  9 - 20
        12: Bereich  9 - 20
        13: Bereich  9 - 20
        14: Bereich  9 - 20
        15: Bereich  9 - 20
        16: Bereich  9 - 20
        17: Bereich  9 - 20
        18: Bereich  9 - 20
        19: Bereich  9 - 20
        20: Bereich  9 - 20
        21: keine Daten
        22: keine Daten
        23: keine Daten
        24: Bereich 24 - 30
        25: Bereich 24 - 30
        26: Bereich 24 - 30
        27: Bereich 24 - 30
        28: Bereich 24 - 30
        29: Bereich 24 - 30
        30: Bereich 24 - 30
        31: keine Daten

        -- Skeeve

  2. Hallo,

    Array
    (
        [0] => 2006-12-02
        [1] => 2006-12-03
        [2] => 2006-12-04
        [3] => 2006-12-05
        [4] => 2006-12-16
        [5] => 2006-12-17
        [6] => 2006-12-18
    )

    $bericht = "2006-12-03"

    okay, soweit kann ich folgen.

    ich will nun das anfangs- und enddatum des zeitraums haben.

    Welches Zeitraums?

    Das wäre hier:
        [0] => 2006-12-02
    ...
        [3] => 2006-12-05
    Wie komme ich zu diesem Ergebnis?

    Das frage ich mich auch gerade, wie du aus einem Einzeldatum (03.Dezember) auf den Zeitraum von 02. bis 05.Dezember kommst.
    Erklär doch bitte noch die Logik, die dahinter steckt.

    So long,
     Martin

    --
    Ungeschehene Ereignisse können einen katastrophalen Mangel an Folgen nach sich ziehen.
      (Unbekannter Politiker)
    1. Moin!

      Das frage ich mich auch gerade, wie du aus einem Einzeldatum (03.Dezember) auf den Zeitraum von 02. bis 05.Dezember kommst.
      Erklär doch bitte noch die Logik, die dahinter steckt.

      Ist gar nicht so schwer. Schau Dir doch mal meine Antwort an ;-) Und vorallem: Schau Dir mal die Daten im Array an... Na? Verstanden?

      -- Skeeve

      1. Hallo,

        Erklär doch bitte noch die Logik, die dahinter steckt.
        Ist gar nicht so schwer. Schau Dir doch mal meine Antwort an ;-)

        da ich das Prinzip, die Logik, nicht verstanden habe, kommt mir deine Antwort auch reichlich konfus vor und verwirrt mich mehr, als dass sie mir etwas sagen könnte.

        Und vorallem: Schau Dir mal die Daten im Array an...

        Sie sind aufsteigend sortiert, okay. Mehr erkenne ich daraus aber nicht. :-(

        Na? Verstanden?

        I'm afraid no.
        So long,
         Martin

        --
        Dieser Satz wurde in mühsamer Kleinstarbeit aus einzelnen Wörtern zusammengesetzt.
          (Hopsel)
        1. Moin!

          Sie sind aufsteigend sortiert, okay. Mehr erkenne ich daraus aber nicht. :-(

          Der Abstand zwischen 2 Einträgen ist fast immer 1. Solche Sequenzen nennt der OP "Zeitraum".

          Meine Vermutung: Im Array steht eine Liste von Tagen, an denen etwas passiert ist (Backup glaufen, Reports erstellt...). Normalerweise passiert das werktäglich (oder täglich ausser an bestimmten Tagen, was weiß ich). Mit der Funktion soll der Zeitraum gefunden werden, in dem das gesuchte Datum liegt.

          -- Skeeve