我需要显示一系列短月日期作为范围。即如果有连续月份的数组,则输出最低和最高月份,并将文本"放在"他们之间。
e.g。阵列' 2月,3月,4月,5月,6月,7月,8月,9月,10月'
输出为' 2月到10月'
如果连续几个月有多组,请为每组进行以上操作
e.g。阵列' 2月,3月,4月,5月,8月,9月,10月'
输出为' 2月至5月,8月至10月'
到目前为止,我已经使用了以下代码但输出在某些月份丢失了。即下面的代码输出' 3月,5月,8月,10月'
$seasons_raw = 'Feb, Mar, Apr, May, Aug, Sep, Oct';
$seasons_arr = explode(",",$seasons_raw);
$seasons_numeric = array();
$seasons_ranges = array();
$group_id = 0;
$last = false;
foreach($seasons_arr as $season_raw){
$month = (int)date('m', strtotime($season_raw));
if($month - $last > 1){
$group_id++;
}
$seasons_numeric[$group_id][] = $month;
$last = $month;
}
foreach($seasons_numeric as $season_section){
$first_obj = DateTime::createFromFormat('!m', $season_section[0]);
$last_obj = DateTime::createFromFormat('!m', $season_section[count($season_section)-1]);
if($first_obj == $last_obj){
$seasons_ranges[] = $first_obj->format('M');
}
else{
$seasons_ranges[] = $first_obj->format('M') . ' to ' . $last_obj->format('M');
}
}
$seasons = implode(', ',$seasons_ranges);
echo $seasons;
由于
答案 0 :(得分:1)
<?php
$input = 'Jan, Feb, Mar, May, Jun, Jul, Aug, Sep, Oct, Dec';
$month_number = array_flip(['Jan','Feb','Mar','Apr','May','Jun','Jul', 'Aug','Sep','Oct','Nov','Dec']);
$input = array_map(function($m) { return trim($m); }, explode(',',$input));
$groups = [];
while ( $current = current($input) ) {
$start = $current;
$i = 0;
do {
$next = next($input);
$i++;
} while ( $next && $month_number[$next] == $month_number[$current] + $i );
$stop = $next ? prev($input) : end($input);
$groups[] = [$start, $stop];
next($input);
}
echo implode(', ', array_map(function($group) {
return $group[0] == $group[1] ? $group[0] : sprintf('%s to %s', $group[0], $group[1]);
}, $groups));
这将输出:
1月至3月,5月至10月,12月
答案 1 :(得分:1)
这不起作用。
$month = (int)date('m', strtotime($season_raw));
替换为自定义功能:
<?php
function debugout($msg) {
echo "DEBUG: " . $msg . "\n";
}
function monthToNum($monthString) {
$m = ['Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, 'May' => 5, 'Jun' => 6,
'Jul' => 7, 'Aug' => 8, 'Sep' => 9, 'Oct' => 10, 'Nov' => 11, 'Dec' => 12];
return $m[trim($monthString)] ?? null;
}
$seasons_raw = 'Feb, Mar, Apr, May, Aug, Sep, Oct';
$seasons_arr = explode(",",$seasons_raw);
$seasons_numeric = array();
$seasons_ranges = array();
$group_id = 0;
$last = false;
foreach($seasons_arr as $season_raw){
// $month = (int)date('m', strtotime($season_raw));
$month = monthToNum($season_raw);
if ( empty($month) ) {
// Check just in case
throw new Exception("Bad month string {$season_raw}");
}
debugout("month '{$season_raw}' -> '{$month}'");
if($month - $last > 1){
$group_id++;
}
$seasons_numeric[$group_id][] = $month;
$last = $month;
}
foreach($seasons_numeric as $season_section){
$first_obj = DateTime::createFromFormat('!m', $season_section[0]);
$last_obj = DateTime::createFromFormat('!m', $season_section[count($season_section)-1]);
if($first_obj == $last_obj){
$seasons_ranges[] = $first_obj->format('M');
}
else{
$seasons_ranges[] = $first_obj->format('M') . ' to ' . $last_obj->format('M');
}
}
$seasons = implode(', ',$seasons_ranges);
echo $seasons;
答案 2 :(得分:1)
只要没有使用多个非连续范围,下面的代码或多或少都会实现目标,可能不会像目前那样精确。在给定输入数据的情况下,我认为不需要实际使用任何date
或DateTime
函数,因此这只适用于数组。
function makerange( $str=false ){
if( $str ){
$tmp=$out=array();
$linear=true;
$year = explode( ',', 'Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec' );
$months = explode( ',', $str );
array_walk( $year, function( &$item ){ $item=trim( $item );});
array_walk( $months, function( &$item ){ $item=trim( $item );});
foreach( $months as $month ){
$tmp[]=array_search( $month, $year );
}
foreach( $tmp as $key => $month ){
if( $key > 0 && $key < count( $tmp ) - 1 ) {
if( $tmp[ $key + 1 ] - $month > 1 ){
$linear=false; break;
}
}
}
if( !empty( $tmp ) ){
$out[]=$year[ $tmp[0] ];
if( !$linear ){
$out[]=$year[ $tmp[ $key ] ];
$out[]=$year[ $tmp[ $key + 1 ] ];
}
$out[]=$year[ $tmp[ count( $tmp ) - 1 ] ];
$bits=array_chunk( $out, 2 );
if( !$linear ){
$from=implode( '-', $bits[ 0 ] );
$to=implode( '-', $bits[ 1 ] );
return sprintf('From: %s To: %s', $from, $to );
} else {
$from = implode( '-', $bits[ 0 ] );
return sprintf('Linear range: %s ', $from );
}
}
return false;
}
}
$str='Feb, Mar, Apr, May, Jun, Aug, Sep, Oct';
printf('%s<br/>%s<br/><br/>', $str, makerange( $str ) );
$str='Jan, Feb, Mar, May, Jun, Jul, Aug, Sep, Oct';
printf('%s<br/>%s<br/><br/>', $str, makerange( $str ) );
以上将输出
Feb, Mar, Apr, May, Jun, Aug, Sep, Oct
From: Feb-Jun To: Aug-Oct
Jan, Feb, Mar, May, Jun, Jul, Aug, Sep, Oct
From: Jan-Mar To: May-Oct
答案 3 :(得分:-2)
编写一个如下所示的简单函数,然后在任意位置调用它。
function ShowMonths($start, $finish = 12)
{
# lets seed month 0 with a NULL so the months can be 1-12
$month[] = NULL;
for ($i=1;$i<13;$i++) {
$month[] = date('M', strtotime('01.'.$i.'.2000'));
}
if ($start < 0 || $start > 11) {
die("Start month incorrect");
}
if ($finish < 1 || $finish > 12) {
die("Finish wrong");
}
if ($start >= $finish) {
die("Finish larger than start");
}
print $month[$start] . " to " . $month[$finish];
}
ShowMonths(1, 2);