添加 X 天至今,不包括周末


Add X Days To Date, Excluding Weekends

我目前正在开发一个在线订阅应用程序。我在用户选择订阅天数和开始日期的部分遇到了一些挑战。然后,PHP 应用程序应该能够计算除周末之外的结束日期。

<form method="post">
    <input name="startdate" type="text" />
    <input name="numberofdays" type="text" />
</form>

有人可以帮助我吗?

取决于startdate的发送方式,但假设您使用的是 Y-m-d,您可以使用 DateTime

例如:

<?php 
    $_POST['startdate'] = '2012-08-14';
    $_POST['numberofdays'] = 10;
    $d = new DateTime( $_POST['startdate'] );
    $t = $d->getTimestamp();
    // loop for X days
    for($i=0; $i<$_POST['numberofdays']; $i++){
        // add 1 day to timestamp
        $addDay = 86400;
        // get what day it is next day
        $nextDay = date('w', ($t+$addDay));
        // if it's Saturday or Sunday get $i-1
        if($nextDay == 0 || $nextDay == 6) {
            $i--;
        }
        // modify timestamp, add 1 day
        $t = $t+$addDay;
    }
    $d->setTimestamp($t);
    echo $d->format( 'Y-m-d' ). "'n";
?>

相同的结果,较短的版本:

function addDays($days,$format="Y-m-d"){
    for($i=0;$i<$days;$i++){
        $day = date('N',strtotime("+".($i+1)."day"));
        if($day>5)
            $days++;
    }
    return date($format,strtotime("+$i day"));
}

轮到我提出一个解决此问题的函数:)

public static function addDaysToDate($startDate, $daysToAdd)
    {
        // loop for X days
        for ($i = 0; $i < $daysToAdd; $i++) {
            // get what day it is next day
            $nextDay = $startDate->modify('+1 day');
            
            // if it's Saturday or Sunday get $i-1
            if (in_array($nextDay->format('w'), [0, 6]) || self::isHoliday($nextDay->getTimestamp())) {
                $i--;
            }
        }
    return $nextDay;
}

isHoliday函数正在确定这一天是否为公共假期:

/**
 * Fonction permettant de retour la date de Pâques au format timestamp
 */
public static function easterDate($year)
{
    $a = $year % 4;
    $b = $year % 7;
    $c = $year % 19;
    $m = 24;
    $n = 5;
    $d = (19 * $c + $m ) % 30;
    $e = (2 * $a + 4 * $b + 6 * $d + $n) % 7;
    $easterdate = 22 + $d + $e;
    if ($easterdate > 31) {
        $day = $d + $e - 9;
        $month = 4;
    } else {
        $day = 22 + $d + $e;
        $month = 3;
    }
    if ($d == 29 && $e == 6) {
        $day = 10;
        $month = 04;
    } elseif ($d == 28 && $e == 6) {
        $day = 18;
        $month = 04;
    }
    return mktime(0, 0, 0, $month, $day, $year);
}
/**
* Fonction permettant de retourner les jours fériés d'une année passée en paramètre
*/
public static function publicHolidays($year)
{
    if ($year === null) {
        $year = intval(strftime('%Y'));
    }
    $easterDate = self::easterDate($year);
    $easterDay = date('j', $easterDate);
    $easterMonth = date('n', $easterDate);
    $easterYear = date('Y', $easterDate);
    $holidays = array(
        // Jours fériés fixes
        mktime(0, 0, 0, 1, 1, $year),// 1er janvier
        mktime(0, 0, 0, 5, 1, $year),// Fête du travail
        mktime(0, 0, 0, 5, 9, $year),// Fête de l'Europe
        mktime(0, 0, 0, 6, 23, $year),// Fête nationale
        mktime(0, 0, 0, 8, 15, $year),// Assomption
        mktime(0, 0, 0, 11, 1, $year),// Toussaint
        mktime(0, 0, 0, 12, 25, $year),// Noël
        mktime(0, 0, 0, 12, 26, $year),// Saint-Etienne
        // Jour fériés qui dépendent de Pâques
        mktime(0, 0, 0, $easterMonth, $easterDay + 1, $easterYear),// Lundi de Pâques
        mktime(0, 0, 0, $easterMonth, $easterDay + 39, $easterYear),// Ascension
        mktime(0, 0, 0, $easterMonth, $easterDay + 50, $easterYear), // Pentecôte
    );
    sort($holidays);
    return $holidays;
}
/**
 * Fonction permettant de savoir si un timestamp d'une date passée en paramètre est férié ou pas
 */
public static function isHoliday($timestamp)
{
    $iYear = strftime('%Y', $timestamp);
    $aHolidays = self::publicHolidays($iYear);
    /*
    * On est obligé de convertir les timestamps en string à cause des décalages horaires.
    */
    $aHolidaysString = array_map(function ($value) {
        return strftime('%Y-%m-%d', $value);
    }, $aHolidays);
    if (in_array(strftime('%Y-%m-%d', $timestamp), $aHolidaysString)) {
        return true;
    }
    return false;
}

希望对您有所帮助!

此致敬意

埃内斯

我今天开发了一个新功能,可以帮助有此类问题的人。

function sumDays($days = 0, $format = 'd/m/Y') {
    $incrementing = $days > 0;
    $days         = abs($days);
    $actualDate   = date('Y-m-d');
    while ($days > 0) {
        $tsDate    = strtotime($actualDate . ' ' . ($incrementing ? '+' : '-') . ' 1 days');
        $actualDate = date('Y-m-d', $tsDate);
        if (date('N', $tsDate) < 6) {
            $days--;
        }
    }
    return date($format, strtotime($actualDate));
}

我今天开发了一个新功能,可以帮助有这种问题的人。取决于开始日期的发送方式,但假设您使用的是 Y-m-d,则可以使用 DateTime

<?php  public static function getOrderEndDate( $start_date, $orderDaysCode ){
    $saturday_off = false;
    if( $orderDaysCode == 'meal_monthly_6' ) { $orderDays = 24; }
    elseif( $orderDaysCode == 'meal_monthly_5' ) {
        $orderDays = 20;
        $saturday_off = true;
    }elseif( $orderDaysCode == 'meal_weekly' ) {
        $orderDays = 5;
        $saturday_off = true;
    }
    else{ $orderDays = 1; }   // Daily Meal
    $formatted_date = new DateTime( $start_date );
    $date_timestamp = $formatted_date->getTimestamp();
    // loop for X days
    for( $i = 0; $i < ( $orderDays - 1 ); $i++ ) {
        // get what day it is next day
        $nextDay = date('w', strtotime('+1day', $date_timestamp) );
        // if it's Sunday or Saturday get $i-1
        if( $nextDay == 0 || ( $nextDay == 6 && $saturday_off ) ) { $i--; }
        // modify timestamp, add 1 day
        $date_timestamp = strtotime('+1day', $date_timestamp);
    }
    $formatted_date->setTimestamp($date_timestamp);
    return $formatted_date->format( 'Y-m-d' );
}
$orderEndDate = getOrderEndDate( '2020-06-17', 'meal_monthly_6' ); ?>

我来这里寻找解决方案。最后,我找到了一个单线解决方案。

<?php 
    echo date('d/m/Y',strtotime("+10 weekdays"));
?>