2012-08-15 62 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