Zend_Date: Как узнать дату наступающего дня? - PullRequest
4 голосов
/ 19 декабря 2009

Я хочу получить дату ближайшего понедельника в будущем (т.е. не в прошлом).

Итак, если сегодня вторник (1 декабря 2009 г.), я хочу получить дату понедельника (7 декабря 2009 г.).

Как я могу сделать это с Zend_Date?

Решение:

Скажем, сегодня вторник, и мы хотели получить предстоящий понедельник. Понедельник - 6 дней в будущем. Итак, мы бы добавили 6 дней, чтобы получить дату понедельника.

//like so:
$tuesday = Zend_Date::now();
$nextMonday = $tuesday->addDay(6);

Чтобы сделать это динамически, нам нужно определить, какой сегодня день недели:

$today = Zend_Date::now();
$dayNumber = $today->get(Zend_Date::WEEKDAY_DIGIT);
//dayNumber will now be equal to the numeric day of the week (0-6)
//example:
$weekdays = array(
    0 => 'sunday',
    1 => 'monday',
    2 => 'tuesday' //etc...
);

Чтобы определить, сколько дней нам нужно добавить, чтобы получить желаемый будущий день, мы делаем следующее:

$daysToAdd = ( $dayWanted - $todayDayNumber + 7 );
#      $dayWanted = monday(1)
# $todayDayNumber = tuesday(2)
#               7 = number of days in a week (we don't want a negative number)
#       1 - 2 + 7 = 6 days into the future
$nextMonday = $today->addDay($daysToAdd);

Скажем, день, который мы хотим, это среда (завтра), один день в будущем. Наше предыдущее решение не сработает:

$daysToAdd = ( $dayWanted - $todayDayNumber + 7 );
#      $dayWanted = wednesday(3)
# $todayDayNumber = tuesday(2)
#               7 = number of days in a week
#       3 - 2 + 7 = 8 days into the future (not 1)

Мы можем решить эту проблему, добавив в нашу формулу оператор модуля (знак процента), чтобы получить остаток от операции деления.

$daysToAdd = ( $dayWanted - $todayDayNumber + 7 ) % 7;
# (3 - 2 + 7) % 7
# $daysToAdd == 1 (remainder of 8 divided by 7)
$tomorrow = $today->addDay($daysToAdd);

Теперь наша формула будет работать как положено ... за исключением одной вещи. Если сегодня вторник, и я хочу получить следующий вторник, наша формула вернется сегодня вместо недели с сегодняшнего дня:

$daysToAdd = ( $dayWanted - $todayDayNumber + 7 ) % 7;
# (2 - 2 + 7) % 7 == 0
# 7 goes into 7 evenly with no remainder

Нам нужно будет добавить проверку, чтобы убедиться, что она не равна нулю.

if ($daysToAdd == 0) {
    //give me the date a week from today, not today's date
    $daysToAdd = 7;
}

Окончательное решение:

public function outputDate()
{
    $monday = $this->getDateOfNext('monday');
    echo 'today: ' . Zend_Date::now()->toString(Zend_Date::RFC_850) . "<br>";
    echo "monday: " . $monday->toString(Zend_Date::RFC_850);
}

private function getDateOfNext($dayWanted)
{
    $weekdays = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
    if (!in_array($dayWanted, $weekdays)) {
        throw new Exception("'$dayWanted' not found in array of possible weekdays");
    }
    $weekdays = array_flip($weekdays);
    $date = Zend_Date::now();
    $today = $date->get(Zend_Date::WEEKDAY_DIGIT);
    $daysToAdd = ( $weekdays[$dayWanted] - $today + 7 ) % 7;
    if ($daysToAdd == 0) {
        //give me the date a week from today, not today's date
        $daysToAdd = 7;
    }
    $date->addDay($daysToAdd);
    return $date;
}

1 Ответ

6 голосов
/ 19 декабря 2009

Вот логика, изложенная:

$days_per_week = 7;
$weekdays = array_flip(array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'));

$day_wanted = 'mon';
$days_forward =
  ( $weekdays[$day_wanted] - $date->get(Zend_Date::WEEKDAY_DIGIT) + $days_per_week )
  % $days_per_week;

$date->addDay($days_forward);

Это прекрасно работает для любого $day_wanted.

...