7

日付の追加、違いの検出、間隔内で週末を除く何日かを調べるなどの日時操作を実際にどのように実行しますか? 私は個人的にこれらの操作のいくつかをpostgresql dbmsに渡し始めました。通常、答えを得るために1つのSQLステートメントを発行するだけでよいためです。ただし、PHPの方法でそれを行うには、より多くのコードを書く必要があり、より多くのチャンスを意味しますエラーが発生するため...

多くのコードを必要としない方法で日時操作を行う PHP のライブラリはありますか? これは、「2 つの日付が与えられた場合、2 つの日付の間に何日間の稼働日があるか?」という状況で sql を打ち負かします。このクエリを作成することで解決される SQL または $pet_lang' で実装しますか?

SELECT  COUNT(*) AS total_days
FROM    (SELECT date '2008-8-26' + generate_series(0,
          (date '2008-9-1' - date '2008-8-26')) AS all_days) AS calendar
WHERE   EXTRACT(isodow FROM all_days) < 6;
4

12 に答える 12

5

ほとんどの日時操作では、通常は Unixtime に変換し、Unixtime 整数に対して加算減算などを実行しますが、Zend フレームワークの Zend_Date クラスを参照することをお勧めします。

これには、あなたが説明する多くの機能があります。Zend は「フレームワーク」として請求されますが、要素を選択して選択するクラス ライブラリとして非常にうまく機能します。私たちは定期的にそれをプロジェクトに含め、必要に応じてビットを取り込んでいます。

于 2008-09-11T13:55:16.717 に答える
2

日付を追加するには、php5.3.0以降で使用可能なメソッドDateTime:: addDateTimeオブジェクトに日、月、年、時間、分、秒の量を追加します)を使用できます。

2つの日付の違いを見つけるために、DateTime::diffメソッドがあります。しかし、2つの日付の間の稼働日数を数える方法はないようです。

于 2010-01-06T14:20:14.190 に答える
2

strtotime() は便利ですが、書式設定された日付/時刻文字列を変換するためだけに使用していない場合、時々ポップアップする可能性のある奇妙な動作がいくつかあります。

「+1 か月」や「-3 日」などでは、期待どおりの結果が得られないことがあります。

于 2008-09-11T21:32:47.240 に答える
2

PEAR::Date便利な機能がありそうです。

PEAR::Calendarも役立つかもしれません。

于 2008-09-11T16:23:04.943 に答える
2

PHP5+ の DateTime オブジェクトは、うるう時間と夏時間に対応しているため便利ですが、実際に問題を解決するには何らかの拡張が必要です。同様の問題を解決するために、次のように書きました。find_WeekdaysFromThisTo() メソッドは強引ですが、期間が 2 年未満の場合はかなり迅速に機能します。

$tryme = new Extended_DateTime('2007-8-26');
$newer = new Extended_DateTime('2008-9-1');

print 'Weekdays From '.$tryme->format('Y-m-d').' To '.$newer->format('Y-m-d').': '.$tryme -> find_WeekdaysFromThisTo($newer) ."\n";
/*  Output:  Weekdays From 2007-08-26 To 2008-09-01: 265  */
print 'All Days From '.$tryme->format('Y-m-d').' To '.$newer->format('Y-m-d').': '.$tryme -> find_AllDaysFromThisTo($newer) ."\n";
/*  Output:  All Days From 2007-08-26 To 2008-09-01: 371   */
$timefrom = $tryme->find_TimeFromThisTo($newer);
print 'Between '.$tryme->format('Y-m-d').' and '.$newer->format('Y-m-d').' there are '.
      $timefrom['years'].' years, '.$timefrom['months'].' months, and '.$timefrom['days'].
      ' days.'."\n";
/*  Output: Between 2007-08-26 and 2008-09-01 there are 1 years, 0 months, and 5 days. */

class Extended_DateTime extends DateTime {

    public function find_TimeFromThisTo($newer) {
        $timefrom = array('years'=>0,'months'=>0,'days'=>0);

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;

        $timefrom['years'] = $this->find_YearsFromThisTo($testnewer);
        $mod = '-'.$timefrom['years'].' years';
        $testnewer -> modify($mod);

        $timefrom['months'] = $this->find_MonthsFromThisTo($testnewer);
        $mod = '-'.$timefrom['months'].' months';
        $testnewer -> modify($mod);

        $timefrom['days'] = $this->find_AllDaysFromThisTo($testnewer);
        return $timefrom;
    } // end function find_TimeFromThisTo


    public function find_YearsFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;
        $count = 0;

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;

        $testnewer -> modify ('-1 year');
        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 year');
        }
        return $count;
    } // end function find_YearsFromThisTo


    public function find_MonthsFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;
        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 month');

        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 month');
        }
        return $count;
    } // end function find_MonthsFromThisTo


    public function find_AllDaysFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;
        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 day');

        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 day');
        }
        return $count;
    } // end function find_AllDaysFromThisTo


    public function find_WeekdaysFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 day');

        while ( $this->format('U') < $testnewer->format('U')) {
            // If the calculated day is not Sunday or Saturday, count this day
            if ($testnewer->format('w') != '0' && $testnewer->format('w') != '6')
                $count ++;
            $testnewer -> modify ('-1 day');
        }
        return $count;
    } // end function find_WeekdaysFromThisTo

    public function set_Day($newday) {
        if (is_int($newday) && $newday > 0 && $newday < 32 && checkdate($this->format('m'),$newday,$this->format('Y')))
            $this->setDate($this->format('Y'),$this->format('m'),$newday);
    } // end function set_Day


    public function set_Month($newmonth) {
        if (is_int($newmonth) && $newmonth > 0 && $newmonth < 13)
            $this->setDate($this->format('Y'),$newmonth,$this->format('d'));
    } // end function set_Month


    public function set_Year($newyear) {
        if (is_int($newyear) && $newyear > 0)
            $this->setDate($newyear,$this->format('m'),$this->format('d'));
    } // end function set_Year
} // end class Extended_DateTime
于 2008-10-14T13:39:41.900 に答える
1

最も簡単な方法は、2008 年 1 月 1 日からの秒数を表すタイムスタンプを使用することです。タイムスタンプ型を使用すると、次のようなことができます...

now = time();
tomorrow = now + 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds

PHP Web ページでtime()date()、およびmktime()のドキュメントを確認してください。これらは、私が最も頻繁に使用する傾向がある 3 つの方法です。

于 2008-09-11T13:58:35.960 に答える
0

日付の計算を行うときは、UNIX タイムスタンプを使用するのではなく、PHP 5.2 のDateTime オブジェクトを使用することを強くお勧めします。UNIX タイムスタンプを返す PHP 日付関数を使用する場合、作業範囲が非常に限られます (たとえば、1970 年より前のものはありません)。

于 2008-09-13T17:09:10.913 に答える
0

strtotimemktime、およびdateの組み合わせを使用して演算を行うことができます

これは、いくつかの算術演算を行うためにコンボを使用する例ですhttp://rushi.wordpress.com/2008/04/13/php-print-out-age-of-date-in-words/ここでコードを再現します簡単にするために

if ($timestamp_diff < (60*60*24*7)) {
   echo floor($timestamp_diff/60/60/24)." Days";
} elseif ($timestamp_diff > (60*60*24*7*4)) {
   echo floor($timestamp_diff/60/60/24/7)." Weeks";
} else {
   $total_months = $months = floor($timestamp_diff/60/60/24/30);
   if($months >= 12) {
      $months = ($total_months % 12);
      $years&nbsp; = ($total_months - $months)/12;
      echo $years . " Years ";
   }
   if($months > 0)
      echo $months . " Months";
}
?>
于 2008-09-11T15:33:37.417 に答える
0

@Rushi個人的にはstrtotime()が好きではありません..理由はわかりませんが、今朝、「2008-09-11 9:5 AM」のような文字列をstrtotimeに渡すとfalseが返されることを発見しました...

あなたが提供したコードは、「2 つの日付が与えられた場合、2 つの日付の間に何日間の稼働日がありますか?」という問題の例を解決するとは思いません。SQL または $pet_lang' で実装しますが、祝日のリストがあるかどうかは考慮していません...

于 2008-09-11T15:39:58.540 に答える
0

If you have a look at http://php.net/date , you will find some examples of using mktime() to perform operations.

A simple example would be to workout what tomorrows date would be. You can do that by simply adding 1, to the day value in mktime() as follows:

$tomorrow = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")));

So here, you will receive a date in the form of YYYY-MM-DD containing tomorrows date. You can also subtract days by simply replacing '+' with '-'. mktime() makes life a lot easier, and saves you from having to do nested if statements and other such troublesome coding.

于 2008-09-12T09:22:57.173 に答える
0

次のように、2 つの日付間の日数を取得できます。

$days = (strtotime("2008-09-10") - strtotime("2008-09-12")) / (60 * 60 * 24);

そして、あなたはそのような関数を作ることができます(私の仕事用コンピュータにはphpがインストールされていないので、構文が100%正しいとは保証できません)

function isWorkDay($date)
{
 // check if workday and return true if so
}

function numberOfWorkDays($startdate, $enddate)
{
  $workdays = 0;
  $tmp = strtotime($startdate);
  $end = strtotime($enddate);
  while($tmp <= $end)
  {
    if ( isWorkDay( date("Y-m-d",$tmp) ) ) $workdays++;
    $tmp += 60*60*24;
  }
  return $workdays;
}

strtotimeが気に入らず、常に同じ形式の日付がある場合は、次のような爆発関数を使用できます

list($year, $month, day) = explode("-", $date);
于 2008-09-12T10:13:39.563 に答える
-1

営業日/休日を取得するには、postgresql CTE ftw -- http://osssmb.wordpress.com/2009/12/02/business-days-working-days-sql-for-postgres-2/を参照してください。

于 2011-07-11T04:43:30.850 に答える