2012-08-15 31 views
2

我有一个功能,接受($year, $month = null, $day = null)优化mysql日期生成器?

基本上一年总是必须通过,但月和日是可选的。
如果他们没有通过,那么它将范围设置为尽可能最大。

这样:call | result

(2012, 08, 15) | ['2012-08-15', '2012-08-15'] 
(2012, 08)  | ['2012-08-01', '2012-08-31'] 
(2012, 02)  | ['2012-02-01', '2012-02-29'] 
(2012)   | ['2012-01-01', '2012-12-31'] 
()    | false 

我有下面的代码,但是对我来说,似乎不必要的复杂性,任何人都可以想出一个更好的版本?

if (!is_null($year)) { 

    //year 
    $from = $year . '-'; 
    $to = $year . '-'; 

    //month 
    if (!is_null($month)) { 
    $from .= sprintf('%02d', $month) . '-'; 
    $to .= sprintf('%02d', $month) . '-'; 

    //day 
    if (!is_null($day)) { 
     $from .= sprintf('%02d', $day); 
     $to .= sprintf('%02d', $day); 
    } else { 
     $from .= '01'; 
     $to .= sprintf('%02d', cal_days_in_month(CAL_GREGORIAN, $month, $year)); 
    } 

    } else { 
    $from .= '01-31'; 
    $to .= '12-31'; 
    } 
    return array($from, $to); 
} 
return false; 

回答

2

首先,让使用更方便我会改变设计有点:

function my_func_your_func_date_func($year, $month = null, $day = null) 
{ 
    if (NULL === $year) 
     return false; 

    $mask = '%04d-%02d-%02d'; 
    $from = vsprintf($mask, date_pad_first($year, $month, $day)); 
    $to = vsprintf($mask, date_pad_last($year, $month, $day)); 

    return array($from, $to); 
} 

,然后将这些辅助功能:

function date_pad_first($year, $month = NULL, $day = NULL) 
{ 
    if (NULL === $month) 
     $month = 1; 

    if (NULL === $day) 
     $day = 1; 

    return array($year, $month, $day); 
} 

function date_pad_last($year, $month = NULL, $day = NULL) 
{ 
    if (NULL === $month) 
     $month = 12; 

    if (NULL === $day) 
     $day = cal_days_in_month(CAL_GREGORIAN, $month, $year); 

    return array($year, $month, $day); 
} 

那么我可能要提取这两个非常相似的功能和参数之间的差异,但我不确定。


如果您喜欢有它一个函数中(和一点点不同的语义重置$day如果$month未设置),这需要有一个if分支:

function my_func_your_func_date_func($year, $month = null, $day = null) 
{ 
    if (NULL === $year) 
     return false; 

    $from[-1] = $year; 
    $to = $from; 

    if (NULL === $month) { 
     $from += [1, 1]; 
     $to += [12, 31]; 
    } else { 
     $from[2] += [$month, 1]; 
     $to[2] += [$month, cal_days_in_month(CAL_GREGORIAN, $month, $year)]; 
    } 

    $mask = '%04d-%02d-%02d'; 
    return array(
     vsprintf($mask, $from), 
     vsprintf($mask, $to) 
    ); 
} 

此功能如果将有一个12月份的时间少于或超过31天,也将不起作用。

0
$format = '%d-%02d-%02d'; 

$to = $from = array ('year' => $year); 

if (! is_null ($month)) 
{ 
    $to['month'] = $from['month'] = $month; 

    if (! is_null ($day)) 
    { 
     $to['day'] = $from['day'] = $day; 
    } 
    else 
    { 
     $from['day'] = '01'; 
     $to['day'] = cal_days_in_month(CAL_GREGORIAN, $month, $year); 
    } 
} 
else 
{ 
    $from += ['month' => '01', 'day' => '01']; 
    $to += ['month' => '12', 'day' => '31']; 
} 

return array (
    vsprintf ($format, $from), 
    vsprintf ($format, $to) 
); 

是这样的吗?

+0

这有一个缺陷。也许它可以在顶部使用'array(-1 => $ year)'。 – hakre 2012-08-15 10:04:41

+0

缺陷在哪里? – DavidS 2012-08-15 10:06:46

+0

比较数组联合运算符的作用:http://php.net/manual/en/language.operators.array.php - 您正在覆盖年份数组键。 – hakre 2012-08-15 10:12:14

0
function my_func_your_func_date_func($year, $month = NAN, $day = NAN) 
{ 
    if (!is_null($year)) { 

    $from_month = max(1, $month); 
    $to_month = min($month,12); 

    $from_day = max(1,$day); 
    $to_day = min($day,cal_days_in_month(CAL_GREGORIAN, $max_m, $year)); 

    $from = sprintf('%s-%02d-%02d',$year,$from_month,$from_day); 
    $to = sprintf('%s-%02d-%02d',$year,$to_month,$to_day); 

    return array($from,$to); 
    } 
    return false; 
} 

min如何,max处理NAN - http://www.php.net/manual/en/function.min.php#101058