Как я могу создать функцию, которая может определить даты последнего дня предыдущего месяца?

У меня есть календарь PHP, в котором перечислены все дни месяца в таблице. До первого дня месяца у меня есть числа за предыдущий месяц, а после последнего дня месяца — числа дней в предстоящем месяце.

Вот фото календаря, как он выглядит сейчас. Как вы можете видеть, нижние серые числа работают нормально, но числа, предшествующие первому дню месяца, являются отрицательными числами и вместо этого должны отображаться как «29,30».

альтернативный текст

Например, числа после последнего дня месяца были просто «32,33,34», поэтому я только что создал оператор if, который проверяет, превышает ли число общее количество дней в текущем месяце, и если да, то например, вычтите общее количество дней в месяце из «32», чтобы оно отображалось как «1,2,3».

if ($day > $total_days_of_current_month) {
  echo '<td>' . ($day - $total_days_of_current_month) . ' </td>'; // for example,33-31=2
}

Моя проблема заключается в создании инструкции if, которая каким-то образом знает, какими были последние дни предыдущего месяца. Проблема в том, что в некоторых месяцах 30 дней, а в некоторых 31 день. Кроме того, февраль и високосные годы являются проблемой. Кто-нибудь знает оператор if, чтобы я мог сделать его отображаемым как «28,29,30» из предыдущего месяца?


person zeckdude    schedule 02.09.2009    source источник


Ответы (6)


Предполагая, что $day является отметкой времени UNIX:

// gets you the first of the month
$date = getdate(mktime(0, 0, 0, date('n', $day), 1, date('Y', $day)));

Отсюда выполните одно из следующих действий:

$lastDayOfPrevMonth = strtotime('-1 day', $date[0]);

// or, better, get the first day "in the grid" (assuming week starts on Sunday)
$date = strtotime("-$date[wday] days", $date[0]);

Я не хочу зацикливаться на этом, но вы посмотрели на мой предыдущий ответ? Это более надежный способ создания календаря вместо всех этих специальных проверок.

person deceze♦    schedule 02.09.2009
comment
Я использую этот php-календарь: iambari.com/2009/05/05/ и я не могу понять, как реализовать ваше решение. Я просто не могу понять, куда его добавить. - person zeckdude; 03.09.2009
comment
Что ж, если вы взламываете уже существующий скрипт, это может быть действительно немного сложно. Мой предыдущий ответ просто демонстрирует другой способ построения всей таблицы календаря, который позволяет избежать всех проблем, с которыми вы сталкиваетесь. Мое решение состоит в том, чтобы проходить фактические даты один день за раз и просто выяснять, как их отображать, вместо того, чтобы просматривать числа 1–31 и пытаться выяснить, какой сегодня день. Вам, вероятно, придется переписать большую часть вашего текущего сценария, чтобы сделать это таким образом. - person deceze♦; 03.09.2009
comment
Начинать дни с последнего воскресенья не позднее первого числа текущего месяца, а не с первого числа месяца. Это все исправляет. - person Robert L; 05.09.2009

Возможно, это может помочь?

cal_days_in_month()

(Отредактировано с учетом отзывов Иншаллы)

person Mark Glasgow    schedule 02.09.2009
comment
Я считаю, что имя функции написано строчными буквами, и вам действительно следует ссылаться на официальную документацию: us2.php.net/manual/en/function.cal-days-in-month.php - person Inshallah; 03.09.2009
comment
спасибо Inshalla, ссылка была указана на официальный сайт (я не сильно прокручивал результаты google). - person Mark Glasgow; 03.09.2009
comment
Нет недостатка в способах сделать это. Например, с одной из функций даты/времени PHP: date('t', strtotime('предыдущий месяц')) - person GZipp; 03.09.2009

Почему бы просто не взять временную метку первого дня месяца и вычесть из нее 24 часа, а затем использовать date('d', $timestamp); ? Кроме того, если у вас есть метка времени в этом месяце, date('t', $timestamp); получит для вас количество дней в месяце.

Краткий пример:

// sets to 3am, first day of month, 3am helps us avoid DST issues with subtracting hours    
$monthStart = mktime(3,0,0,date('n'),1,date('Y')); 
$thisMonth = date('n', $monthStart);

// rewind to the sunday before- date('w') is the "weekday" 0 based    
$date = $monthStart - (date('w',$monthStart) * 60 * 60 * 24);     

while ($date<$monthStart || date('n', $date) == $thisMonth)
{
  echo "<tr>";
  for ($x=0; $x<7; $x++) {
    echo "<td";
    if (date('n', $date) != $thisMonth) echo " class='notMonth'";
    echo ">";
    echo date("j", $date);
    echo "</td>";
    $date += 60*60*24;
  }
  echo "</tr>\n";
}
person gnarf    schedule 02.09.2009
comment
Вместо того, чтобы вычесть 24 часа, вы должны вычесть 1 день. Причина в том, что иногда в днях больше или меньше 24 часов (например, летнее время, високосные секунды и т. д.), что, если бы это произошло 1-го числа месяца, отбросило бы ваш расчет. - person Asaph; 03.09.2009
comment
Вот почему я установил час исходной даты на 3 часа ночи, +/- 1 час летнего времени не испортит дату. При создании календаря час в любом случае не имеет значения. - person gnarf; 03.09.2009

Взгляните на исходный код проекта PHP-Calender-Class:

http://code.google.com/p/php-calendar-class/< /а>

источник класса: http://code.google.com/p/php-calendar-class/source/browse/trunk/calendar.class.php

Это может дать вам некоторое представление о проблеме.

person bucabay    schedule 02.09.2009

Используя cal_days_in_month(), как насчет добавления следующего кода:

if ($day < 1) {
  echo '<td>' . ($day + cal_days_in_month(
     CAL_GREGORIAN,date_format("n",
         date_add(date_create(),"P-1M")))) . ' </td>'; // for example,-1 + 30 = 29th
}

EDITED: добавлена ​​функция date_format

person Scott Lundberg    schedule 03.09.2009

Подождите... ваше название месяца вверху неправильное! Там написано "август 2009", но в месяце 30 дней, а дни недели как раз для сентября 2009!

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

person Robert L    schedule 04.09.2009