优化 mysql 日期生成器


Optimizing mysql date generator?

我有一个接受($year, $month = null, $day = null)的函数

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

所以: 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;

首先,我会稍微改变一下设计,以便使用起来更容易:

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);
}

然后,我可能想提取这两个看起来非常相似的函数之间的差异并对其进行参数化,但我不确定。


如果您希望将其放在一个函数中(如果未设置$month则使用稍微不同的语义重置$day),则需要使用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)
    );
}

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

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;
}

了解 minmax如何处理NAN - http://www.php.net/manual/en/function.min.php#101058

$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)
);

像这样的东西?