[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/date/date_repeat/ -> date_repeat_calc.inc (source)

   1  <?php
   2  /**
   3   * @file
   4   * Code to compute the dates that match an iCal RRULE.
   5   *
   6   * Moved to a separate file since it is not used on most pages
   7   * so the code is not parsed unless needed.
   8   *
   9   * Extensive simpletests have been created to test the RRULE calculation
  10   * results against official examples from RFC 2445.
  11   *
  12   * These calculations are expensive and results should be stored or cached
  13   * so the calculation code is not called more often than necessary.
  14   *
  15   * Currently implemented:
  16   * INTERVAL, UNTIL, COUNT, EXDATE, RDATE, BYDAY, BYMONTHDAY, BYMONTH,
  17   * YEARLY, MONTHLY, WEEKLY, DAILY
  18   *
  19   * Currently not implemented:
  20   *
  21   * BYYEARDAY, MINUTELY, HOURLY, SECONDLY, BYMINUTE, BYHOUR, BYSECOND
  22   *   These could be implemented in the future.
  23   *
  24   * BYSETPOS
  25   *   Seldom used anywhere, so no reason to complicated the code.
  26   */
  27  
  28  /**
  29   * Private implementation of date_repeat_calc().
  30   *
  31   * Compute dates that match the requested rule, within a specified date range.
  32   */
  33  function _date_repeat_calc($rrule, $start, $end, $exceptions, $timezone, $additions) {
  34    module_load_include('inc', 'date_api', 'date_api_ical');
  35  
  36    if (empty($timezone)) {
  37      $timezone = date_default_timezone_name();
  38    }
  39  
  40    // Make sure the 'EXCEPTIONS' string isn't appended to the rule.
  41    $parts = explode("\n", $rrule);
  42    if (count($parts)) {
  43      $rrule = $parts[0];
  44    }
  45    // Get the parsed array of rule values.
  46    $rrule = date_ical_parse_rrule('RRULE:', $rrule);
  47  
  48    // These default values indicate there is no RRULE here.
  49    if ($rrule['FREQ'] == 'NONE' || (isset($rrule['INTERVAL']) && $rrule['INTERVAL'] == 0)) {
  50      return array();
  51    }
  52  
  53    // Create a date object for the start and end dates.
  54    $start_date = date_make_date($start, $timezone);
  55  
  56    // Versions of PHP greater than PHP 5.3.5 require that we set an explicit time when
  57    // using date_modify() or the time may not match the original value. Adding this
  58    // modifier gives us the same results in both older and newer versions of PHP.
  59    $modify_time = ' ' . $start_date->format('g:ia');
  60  
  61    // If the rule has an UNTIL, see if that is earlier than the end date.
  62    if (!empty($rrule['UNTIL'])) {
  63      $end_date = date_make_date($end, $timezone);
  64      $until_date = date_ical_date($rrule['UNTIL'], $timezone);
  65      if (date_format($until_date, 'U') < date_format($end_date, 'U')) {
  66        $end_date = $until_date;
  67      }
  68    }
  69    // The only valid option for an empty end date is when we have a count.
  70    elseif (empty($end)) {
  71      if (!empty($rrule['COUNT'])) {
  72        $end_date = NULL;
  73      }
  74      else {
  75        return array();
  76      }
  77    }
  78    else {
  79      $end_date = date_make_date($end, $timezone);
  80    }
  81  
  82    // Get an integer value for the interval, if none given, '1' is implied.
  83    if (empty($rrule['INTERVAL'])) {
  84      $rrule['INTERVAL'] = 1;
  85    }
  86    $interval = max(1, $rrule['INTERVAL']);
  87    $count = isset($rrule['COUNT']) ? $rrule['COUNT'] : NULL;
  88  
  89    if (empty($rrule['FREQ'])) {
  90      $rrule['FREQ'] = 'DAILY';
  91    }
  92  
  93    // Make sure DAILY frequency isn't used in places it won't work;
  94    if (!empty($rrule['BYMONTHDAY']) && !in_array($rrule['FREQ'], array('MONTHLY', 'YEARLY'))) {
  95      $rrule['FREQ'] = 'MONTHLY';
  96    }
  97    elseif (!empty($rrule['BYDAY']) && !in_array($rrule['FREQ'], array('MONTHLY', 'WEEKLY', 'YEARLY'))) {
  98      $rrule['FREQ'] = 'WEEKLY';
  99     }
 100  
 101    // Find the time period to jump forward between dates.
 102    switch ($rrule['FREQ']) {
 103     case 'DAILY':
 104       $jump = $interval . ' days';
 105       break;
 106     case 'WEEKLY':
 107       $jump = $interval . ' weeks';
 108       break;
 109     case 'MONTHLY':
 110       $jump = $interval . ' months';
 111       break;
 112     case 'YEARLY':
 113       $jump = $interval . ' years';
 114       break;
 115    }
 116    $rrule = date_repeat_adjust_rrule($rrule, $start_date);
 117  
 118    // The start date always goes into the results, whether or not it meets
 119    // the rules. RFC 2445 includes examples where the start date DOES NOT
 120    // meet the rules, but the expected results always include the start date.
 121    $days = array(date_format($start_date, DATE_FORMAT_DATETIME));
 122  
 123    // BYMONTHDAY will look for specific days of the month in one or more months.
 124    // This process is only valid when frequency is monthly or yearly.
 125  
 126    if (!empty($rrule['BYMONTHDAY'])) {
 127      $finished = FALSE;
 128      $current_day = drupal_clone($start_date);
 129      $direction_days = array();
 130      // Deconstruct the day in case it has a negative modifier.
 131      foreach ($rrule['BYMONTHDAY'] as $day) {
 132        preg_match("@(-)?([0-9]{1,2})@", $day, $regs);
 133        if (!empty($regs[2])) {
 134          // Convert parameters into full day name, count, and direction.
 135          $direction_days[$day] = array(
 136            'direction' => !empty($regs[1]) ? $regs[1] : '+',
 137            'direction_count' => $regs[2],
 138            );
 139        }
 140      }
 141      while (!$finished) {
 142        $period_finished = FALSE;
 143        while (!$period_finished) {
 144          foreach ($rrule['BYMONTHDAY'] as $monthday) {
 145            $day = $direction_days[$monthday];
 146            $current_day = date_repeat_set_month_day($current_day, NULL, $day['direction_count'], $day['direction'], $timezone, $modify_time);
 147            date_repeat_add_dates($days, $current_day, $start_date, $end_date, $exceptions, $rrule);
 148            if ($finished = date_repeat_is_finished($current_day, $days, $count, $end_date)) {
 149              $period_finished = TRUE;
 150            }
 151          }
 152          // If it's monthly, keep looping through months, one INTERVAL at a time.
 153          if ($rrule['FREQ'] == 'MONTHLY') {
 154            if ($finished = date_repeat_is_finished($current_day, $days, $count, $end_date)) {
 155              $period_finished = TRUE;
 156            }
 157            // Back up to first of month and jump.
 158            $current_day = date_repeat_set_month_day($current_day, NULL, 1, '+', $timezone, $modify_time);
 159            date_modify($current_day, '+' . $jump . $modify_time);
 160          }
 161          // If it's yearly, break out of the loop at the
 162          // end of every year, and jump one INTERVAL in years.
 163          else {
 164            if (date_format($current_day, 'n') == 12) {
 165              $period_finished = TRUE;
 166            }
 167            else {
 168              // Back up to first of month and jump.
 169              $current_day = date_repeat_set_month_day($current_day, NULL, 1, '+', $timezone, $modify_time);
 170              date_modify($current_day, '+1 month' . $modify_time);
 171            }
 172          }
 173        }
 174        if ($rrule['FREQ'] == 'YEARLY') {
 175          // Back up to first of year and jump.
 176          $current_day = date_repeat_set_year_day($current_day, NULL, 1, '+', $timezone, $modify_time);
 177          date_modify($current_day, '+' . $jump . $modify_time);
 178        }
 179        $finished = date_repeat_is_finished($current_day, $days, $count, $end_date);
 180      }
 181    }
 182  
 183    // This is the simple fallback case, not looking for any BYDAY,
 184    // just repeating the start date. Because of imputed BYDAY above, this
 185    // will only test TRUE for a DAILY or less frequency (like HOURLY).
 186  
 187    elseif (empty($rrule['BYDAY'])) {
 188      // $current_day will keep track of where we are in the calculation.
 189      $current_day = drupal_clone($start_date);
 190      $finished = FALSE;
 191      $months = !empty($rrule['BYMONTH']) ? $rrule['BYMONTH'] : array();
 192      while (!$finished) {
 193        date_repeat_add_dates($days, $current_day, $start_date, $end_date, $exceptions, $rrule);
 194        $finished = date_repeat_is_finished($current_day, $days, $count, $end_date);
 195        date_modify($current_day, '+' . $jump . $modify_time);
 196      }
 197    }
 198  
 199    else {
 200  
 201      // More complex searches for day names and criteria like '-1SU' or '2TU,2TH',
 202      // require that we interate through the whole time period checking each BYDAY.
 203  
 204      // Create helper array to pull day names out of iCal day strings.
 205      $day_names = date_repeat_dow_day_options(FALSE);
 206      $days_of_week = array_keys($day_names);
 207  
 208      // Parse out information about the BYDAYs and separate them
 209      // depending on whether they have directional parameters like -1SU or 2TH.
 210      $month_days = array();
 211      $week_days = array();
 212  
 213      // Find the right first day of the week to use, iCal rules say Monday
 214      // should be used if none is specified.
 215      $week_start_rule = !empty($rrule['WKST']) ? trim($rrule['WKST']) : 'MO';
 216      $week_start_day = $day_names[$week_start_rule];
 217  
 218      // Make sure the week days array is sorted into week order,
 219      // we use the $ordered_keys to get the right values into the key
 220      // and force the array to that order. Needed later when we
 221      // iterate through each week looking for days so we don't
 222      // jump to the next week when we hit a day out of order.
 223      $ordered = date_repeat_days_ordered($week_start_rule);
 224      $ordered_keys = array_flip($ordered);
 225  
 226      foreach ($rrule['BYDAY'] as $day) {
 227        preg_match("@(-)?([0-9]+)?([SU|MO|TU|WE|TH|FR|SA]{2})@", trim($day), $regs);
 228        if (!empty($regs[2])) {
 229          // Convert parameters into full day name, count, and direction.
 230          $direction_days[] = array(
 231            'day' => $day_names[$regs[3]],
 232            'direction' => !empty($regs[1]) ? $regs[1] : '+',
 233            'direction_count' => $regs[2],
 234            );
 235        }
 236        else {
 237          $week_days[$ordered_keys[$regs[3]]] = $day_names[$regs[3]];
 238        }
 239      }
 240      ksort($week_days);
 241  
 242      // BYDAYs with parameters like -1SU (last Sun) or 2TH (second Thur)
 243      // need to be processed one month or year at a time.
 244      if (!empty($direction_days) && in_array($rrule['FREQ'], array('MONTHLY', 'YEARLY'))) {
 245        $finished = FALSE;
 246        $current_day = drupal_clone($start_date);
 247        while (!$finished) {
 248          foreach ($direction_days as $day) {
 249            // Find the BYDAY date in the current month.
 250            if ($rrule['FREQ'] == 'MONTHLY') {
 251              $current_day = date_repeat_set_month_day($current_day, $day['day'], $day['direction_count'], $day['direction'], $timezone, $modify_time);
 252            }
 253            else {
 254              $current_day = date_repeat_set_year_day($current_day, $day['day'], $day['direction_count'], $day['direction'], $timezone, $modify_time);
 255            }
 256            date_repeat_add_dates($days, $current_day, $start_date, $end_date, $exceptions, $rrule);
 257          }
 258          $finished = date_repeat_is_finished($current_day, $days, $count, $end_date);
 259          // Reset to beginning of period before jumping to next period.
 260          // Needed especially when working with values like 'last Saturday'
 261          // to be sure we don't skip months like February.
 262          $year = date_format($current_day, 'Y');
 263          $month = date_format($current_day, 'n');
 264          if ($rrule['FREQ'] == 'MONTHLY') {
 265            date_date_set($current_day, $year, $month, 1);
 266          }
 267          else {
 268            date_date_set($current_day, $year, 1, 1);
 269          }
 270          // Jump to the next period.
 271          date_modify($current_day, '+' . $jump . $modify_time);
 272        }
 273      }
 274  
 275      // For BYDAYs without parameters,like TU,TH (every Tues and Thur),
 276      // we look for every one of those days during the frequency period.
 277      // Iterate through periods of a WEEK, MONTH, or YEAR, checking for
 278      // the days of the week that match our criteria for each week in the
 279      // period, then jumping ahead to the next week, month, or year,
 280      // an INTERVAL at a time.
 281  
 282      if (!empty($week_days) && in_array($rrule['FREQ'], array('MONTHLY', 'WEEKLY', 'YEARLY'))) {
 283        $finished = FALSE;
 284        $current_day = drupal_clone($start_date);
 285        $format = $rrule['FREQ'] == 'YEARLY' ? 'Y' : 'n';
 286        $current_period = date_format($current_day, $format);
 287  
 288        // Back up to the beginning of the week in case we are somewhere in the
 289        // middle of the possible week days, needed so we don't prematurely
 290        // jump to the next week. The date_repeat_add_dates() function will
 291        // keep dates outside the range from getting added.
 292        if (date_format($current_day, 'l') != $day_names[$day]) {
 293          date_modify($current_day, '-1 ' . $week_start_day . $modify_time);
 294        }
 295        while (!$finished) {
 296          $period_finished = FALSE;
 297          while (!$period_finished) {
 298            $moved = FALSE;
 299            foreach ($week_days as $delta => $day) {
 300              // Find the next occurence of each day in this week, only add it
 301              // if we are still in the current month or year. The date_repeat_add_dates
 302              // function is insufficient to test whether to include this date
 303              // if we are using a rule like 'every other month', so we must
 304              // explicitly test it here.
 305  
 306              // If we're already on the right day, don't jump or we
 307              // will prematurely move into the next week.
 308              if (date_format($current_day, 'l') != $day) {
 309                date_modify($current_day, '+1 ' . $day . $modify_time);
 310                $moved = TRUE;
 311              }
 312              if ($rrule['FREQ'] == 'WEEKLY' || date_format($current_day, $format) == $current_period) {
 313                date_repeat_add_dates($days, $current_day, $start_date, $end_date, $exceptions, $rrule);
 314              }
 315            }
 316            $finished = date_repeat_is_finished($current_day, $days, $count, $end_date);
 317  
 318            // Make sure we don't get stuck in endless loop if the current
 319            // day never got changed above.
 320            if (!$moved) {
 321              date_modify($current_day, '+1 day' . $modify_time);
 322            }
 323  
 324            // If this is a WEEKLY frequency, stop after each week,
 325            // otherwise, stop when we've moved outside the current period.
 326            // Jump to the end of the week, then test the period.
 327            if ($finished || $rrule['FREQ'] == 'WEEKLY') {
 328              $period_finished = TRUE;
 329            }
 330            elseif ($rrule['FREQ'] != 'WEEKLY' && date_format($current_day, $format) != $current_period) {
 331              $period_finished = TRUE;
 332            }
 333          }
 334  
 335          if ($finished) {
 336            continue;
 337          }
 338  
 339          // We'll be at the end of a week, month, or year when
 340          // we get to this point in the code.
 341  
 342          // Go back to the beginning of this period before we jump, to
 343          // ensure we jump to the first day of the next period.
 344          switch ($rrule['FREQ']) {
 345            case 'WEEKLY':
 346              date_modify($current_day, '+1 ' . $week_start_day . $modify_time);
 347              date_modify($current_day, '-1 week' . $modify_time);
 348              break;
 349            case 'MONTHLY':
 350              date_modify($current_day, '-' . (date_format($current_day, 'j') - 1) . ' days' . $modify_time);
 351              date_modify($current_day, '-1 month' . $modify_time);
 352              break;
 353            case 'YEARLY':
 354              date_modify($current_day, '-' . date_format($current_day, 'z') . ' days' . $modify_time);
 355              date_modify($current_day, '-1 year' . $modify_time);
 356              break;
 357          }
 358          // Jump ahead to the next period to be evaluated.
 359          date_modify($current_day, '+' . $jump . $modify_time);
 360          $current_period = date_format($current_day, $format);
 361          $finished = date_repeat_is_finished($current_day, $days, $count, $end_date);
 362        }
 363      }
 364    }
 365  
 366    // add additional dates
 367    foreach ($additions as $addition) {
 368      $date = date_make_date($addition . ' ' . date_format($start_date, 'H:i:s'), $timezone);
 369      $days[] = date_format($date, DATE_FORMAT_DATETIME);
 370    }
 371  
 372    sort($days);
 373    return $days;
 374  }
 375  
 376  /**
 377   * See if the RRULE needs some imputed values added to it.
 378   */
 379  function date_repeat_adjust_rrule($rrule, $start_date) {
 380    // If this is not a valid value, do nothing;
 381    if (empty($rrule) || empty($rrule['FREQ'])) {
 382      return array();
 383    }
 384  
 385    // RFC 2445 says if no day or monthday is specified when creating repeats for
 386    // weeks, months, or years, impute the value from the start date.
 387  
 388    if (empty($rrule['BYDAY']) && $rrule['FREQ'] == 'WEEKLY') {
 389      $rrule['BYDAY'] = array(date_repeat_dow2day(date_format($start_date, 'w')));
 390    }
 391    elseif (empty($rrule['BYDAY']) && empty($rrule['BYMONTHDAY']) && $rrule['FREQ'] == 'MONTHLY') {
 392      $rrule['BYMONTHDAY'] = array(date_format($start_date, 'j'));
 393    }
 394    elseif (empty($rrule['BYDAY']) && empty($rrule['BYMONTHDAY']) && empty($rrule['BYYEARDAY']) && $rrule['FREQ'] == 'YEARLY') {
 395      $rrule['BYMONTHDAY'] = array(date_format($start_date, 'j'));
 396      if (empty($rrule['BYMONTH'])) {
 397        $rrule['BYMONTH'] = array(date_format($start_date, 'n'));
 398      }
 399    }
 400    // If we are processing rules for period other than YEARLY or MONTHLY
 401    // and have BYDAYS like 2SU or -1SA, simplify them to SU or SA since the
 402    // position rules make no sense in other periods and just add complexity.
 403  
 404    elseif (!empty($rrule['BYDAY']) && !in_array($rrule['FREQ'], array('MONTHLY', 'YEARLY'))) {
 405      foreach ($rrule['BYDAY'] as $delta => $BYDAY) {
 406        $rrule['BYDAY'][$delta] = substr($BYDAY, -2);
 407      }
 408    }
 409  
 410    return $rrule;
 411  }
 412  
 413  /**
 414   * Helper function to add found date to the $dates array.
 415   *
 416   * Check that the date to be added is between the start and end date
 417   * and that it is not in the $exceptions, nor already in the $days array,
 418   * and that it meets other criteria in the RRULE.
 419   */
 420  function date_repeat_add_dates(&$days, $current_day, $start_date, $end_date, $exceptions, $rrule) {
 421    if (isset($rrule['COUNT']) && sizeof($days) >= $rrule['COUNT']) {
 422      return FALSE;
 423    }
 424    $formatted = date_format($current_day, DATE_FORMAT_DATETIME);
 425    if (!empty($end_date) && $formatted > date_format($end_date, DATE_FORMAT_DATETIME)) {
 426      return FALSE;
 427    }
 428    if ($formatted < date_format($start_date, DATE_FORMAT_DATETIME)) {
 429      return FALSE;
 430    }
 431    if (in_array(date_format($current_day, 'Y-m-d'), $exceptions)) {
 432      return FALSE;
 433    }
 434    if (!empty($rrule['BYDAY'])) {
 435      $BYDAYS = $rrule['BYDAY'];
 436      foreach ($BYDAYS as $delta => $BYDAY) {
 437        $BYDAYS[$delta] = substr($BYDAY, -2);
 438      }
 439      if (!in_array(date_repeat_dow2day(date_format($current_day, 'w')), $BYDAYS)) {
 440        return FALSE;
 441      }}
 442    if (!empty($rrule['BYYEAR']) && !in_array(date_format($current_day, 'Y'), $rrule['BYYEAR'])) {
 443      return FALSE;
 444    }
 445    if (!empty($rrule['BYMONTH']) && !in_array(date_format($current_day, 'n'), $rrule['BYMONTH'])) {
 446      return FALSE;
 447    }
 448    if (!empty($rrule['BYMONTHDAY'])) {
 449      // Test month days, but only if there are no negative numbers.
 450      $test = TRUE;
 451      $BYMONTHDAYS = array();
 452      foreach ($rrule['BYMONTHDAY'] as $day) {
 453        if ($day > 0) {
 454          $BYMONTHDAYS[] = $day;
 455        }
 456        else {
 457          $test = FALSE;
 458          break;
 459        }
 460      }
 461      if ($test && !empty($BYMONTHDAYS) && !in_array(date_format($current_day, 'j'), $BYMONTHDAYS)) {
 462        return FALSE;
 463      }
 464    }
 465    // Don't add a day if it is already saved so we don't throw the count off.
 466    if (in_array($formatted, $days)) {
 467      return TRUE;
 468    }
 469    else {
 470      $days[] = $formatted;
 471    }
 472  }
 473  
 474  /**
 475   * Stop when $current_day is greater than $end_date or $count is reached.
 476   */
 477  function date_repeat_is_finished($current_day, $days, $count, $end_date) {
 478    if (($count && sizeof($days) >= $count)
 479    || (!empty($end_date) && date_format($current_day, 'U') > date_format($end_date, 'U'))) {
 480      return TRUE;
 481    }
 482    else {
 483      return FALSE;
 484    }
 485  }
 486  
 487  /**
 488   * Set a date object to a specific day of the month.
 489   *
 490   * Example,
 491   *   date_set_month_day($date, 'Sunday', 2, '-')
 492   *   will reset $date to the second to last Sunday in the month.
 493   *   If $day is empty, will set to the number of days from the
 494   *   beginning or end of the month.
 495   */
 496  function date_repeat_set_month_day($date_in, $day, $count = 1, $direction = '+', $timezone = 'UTC', $modify_time) {
 497    if (is_object($date_in)) {
 498      $current_month = date_format($date_in, 'n');
 499  
 500      // Reset to the start of the month.
 501      // We should be able to do this with date_date_set(), but
 502      // for some reason the date occasionally gets confused if run
 503      // through this function multiple times. It seems to work
 504      // reliably if we create a new object each time.
 505      $datetime = date_format($date_in, DATE_FORMAT_DATETIME);
 506      $datetime = substr_replace($datetime, '01', 8, 2);
 507      $date = date_make_date($datetime, $timezone);
 508      if ($direction == '-') {
 509        // For negative search, start from the end of the month.
 510        date_modify($date, '+1 month' . $modify_time);
 511      }
 512      else {
 513        // For positive search, back up one day to get outside the
 514        // current month, so we can catch the first of the month.
 515        date_modify($date, '-1 day' . $modify_time);
 516      }
 517  
 518      if (empty($day)) {
 519        date_modify($date, $direction . $count . ' days' . $modify_time);
 520      }
 521      else {
 522        // Use the English text for order, like First Sunday
 523        // instead of +1 Sunday to overcome PHP5 bug, (see #369020).
 524        $order = date_order();
 525        $step = $count <= 5 ? $order[$direction . $count] : $count;
 526        date_modify($date, $step . ' ' . $day . $modify_time);
 527      }
 528  
 529      // If that takes us outside the current month, don't go there.
 530      if (date_format($date, 'n') == $current_month) {
 531        return $date;
 532      }
 533    }
 534    return $date_in;
 535  }
 536  
 537  /**
 538   * Set a date object to a specific day of the year.
 539   *
 540   * Example,
 541   *   date_set_year_day($date, 'Sunday', 2, '-')
 542   *   will reset $date to the second to last Sunday in the year.
 543   *   If $day is empty, will set to the number of days from the
 544   *   beginning or end of the year.
 545   */
 546  function date_repeat_set_year_day($date_in, $day, $count = 1, $direction = '+', $timezone = 'UTC', $modify_time) {
 547    if (is_object($date_in)) {
 548      $current_year = date_format($date_in, 'Y');
 549  
 550      // Reset to the start of the month.
 551      // See note above.
 552      $datetime = date_format($date_in, DATE_FORMAT_DATETIME);
 553      $datetime = substr_replace($datetime, '01-01', 5, 5);
 554      $date = date_make_date($datetime, $timezone);
 555      if ($direction == '-') {
 556        // For negative search, start from the end of the year.
 557        date_modify($date, '+1 year' . $modify_time);
 558      }
 559      else {
 560        // For positive search, back up one day to get outside the
 561        // current year, so we can catch the first of the year.
 562        date_modify($date, '-1 day' . $modify_time);
 563      }
 564      if (empty($day)) {
 565        date_modify($date, $direction . $count . ' days' . $modify_time);
 566      }
 567      else {
 568        // Use the English text for order, like First Sunday
 569        // instead of +1 Sunday to overcome PHP5 bug, (see #369020).
 570        $order = date_order();
 571        $step = $count <= 5 ? $order[$direction . $count] : $count;
 572        date_modify($date, $step . ' ' . $day . $modify_time);
 573      }
 574  
 575      // If that takes us outside the current year, don't go there.
 576      if (date_format($date, 'Y') == $current_year) {
 577        return $date;
 578      }
 579    }
 580    return $date_in;
 581  }


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7