将工作日列表转换为间隔

时间:2011-05-16 15:47:21

标签: php arrays dayofweek

我正在寻找一个功能,如果连续3天或更多天相互跟随,则会从工作日序列中删除一周中的几天。这是我的测试代码(使用Test::More测试框架)

// function is($result, $expected, $message)
is(drop_days(""), "", 'Empty');
is(drop_days("Mo"), "Mo", 'One Day');
is(drop_days("Mo,Tu"), "Mo,Tu", 'Two Days');
is(drop_days("Mo,Tu,We"), "Mo-We", 'Three Days');
is(drop_days("Mo,Tu,We,Th,Fr,Sa,Su"), "Mo-Su", 'Seven Days');
is(drop_days("Mo,Tu,Th,Fr"), "Mo,Tu,Th,Fr", 'Four days with gap');
is(drop_days("Mo,Tu,We,Fr"), "Mo-We,Fr", '3 consecutive days, one single day');
is(drop_days("Mo,Tu,We,Fr,Sa,Su"), "Mo-We,Fr-Su", '2 pairs of 3 consecutive days');

3 个答案:

答案 0 :(得分:4)

有时候“愚蠢”的方法是最聪明的

function drop_days($s) {
    static $map  = array(
        'Mo,Tu,We,Th,Fr,Sa,Su' => 'Mo-Su',
        'Mo,Tu,We,Th,Fr,Sa'    => 'Mo-Sa',
        'Mo,Tu,We,Th,Fr'       => 'Mo-Fr',
        'Mo,Tu,We,Th'          => 'Mo-Th',
        'Mo,Tu,We'             => 'Mo-We',
        'Tu,We,Th,Fr,Sa,Su'    => 'Tu-Su',
        'Tu,We,Th,Fr,Sa'       => 'Tu-Sa',
        'Tu,We,Th,Fr'          => 'Tu-Fr',
        'Tu,We,Th'             => 'Tu-Th',
        'We,Th,Fr,Sa,Su'       => 'We-Su',
        'We,Th,Fr,Sa'          => 'We-Sa',
        'We,Th,Fr'             => 'We-Fr',
        'Th,Fr,Sa,Su'          => 'Th-Su',
        'Th,Fr,Sa'             => 'Th-Sa',
        'Fr,Sa,Su'             => 'Fr-Su',
    );
    return strtr($s, $map);
}

答案 1 :(得分:1)

另一种方法:

function drop_days( $str, $days = 'mo,tu,we,th,fr,sa,su' ) {
    $days_i_s = array_flip( explode( ',', $days ) );
    $days_i_n = explode( ',', $days );
    $day_string = str_replace( array_keys( $days_i_s ), array_values( $days_i_s ), strtolower( $str ) );
    return str_replace( array_values( $days_i_s ), array_keys( $days_i_s ), preg_replace_callback( '~(0,1,2,3,4,5,6)|(1,2,3,4,5,6)|(0,1,2,3,4,5)|(1,2,3,4,5)|(2,3,4,5,6)|(0,1,2,3,4)|(0,1,2,3)|(0,1,2)|(3,4,5,6)|(2,3,4,5)|(2,3,4)|(3,4,5)|(1,2,3,4)|(1,2,3)|(2,3,4)|(4,5,6)~', function($m) use($days_i_n){return $days_i_n[$m[0][0]].'-'.$days_i_n[$m[0][strlen($m[0])-1]] ;}, $day_string ) );
}

echo drop_days( "Mo,Tu,We,Fr,Sa,Su" );

答案 2 :(得分:0)

is()位于http://codepad.org/ulJnW3Iu的示例。函数可以按任何顺序接受工作日。

<?php
function drop_days($string, $atleast = 3) {
    $weekdays = 'Mo,Tu,We,Th,Fr,Sa,Su';
    $weekdays = explode(',', $weekdays);
    $selected = array();
    $sequences = array();
    foreach ($weekdays as $weekday)
        $selected[] = (strpos($string,$weekday)!==false);
    $i = 0;
    while ($i<count($weekdays)) {
        if (!$selected[$i]) {
            $i++;
            continue;
        }
        if ($i+$atleast<=count($weekdays)) {
            for ($j=$i+1; $j<count($weekdays); $j++) {
                if ($selected[$j]) {
                    if ($j+1<count($weekdays)) continue;
                    $sequences[] = $weekdays[$i] . '-' . $weekdays[$j];
                    break 2;
                } else {
                    if ($j-$i>=$atleast)
                        $sequences[] = $weekdays[$i] . '-' . $weekdays[$j-1];
                    else
                        for ($k=$i; $k<$j; $k++) $sequences[] = $weekdays[$k];
                    $i = $j+1;
                    break;
                }
            }
        } else {
            $sequences[] = $weekdays[$i];
            $i++;
        }
    }
    return implode(',', $sequences);
}
?>