Frage

Wie führen Sie eigentlich datetime-Operationen wie das hinzufügen von Datum, finden Unterschied, finden Sie heraus, wie viele Tage ohne Wochenenden in einem Intervall?Ich persönlich begann zu passieren einige dieser Operationen zu meiner postgresql-dbms in der Regel als würde ich nur ausgeben müssen, die eine sql-Anweisung, um eine Antwort erhalten, aber, es zu tun in PHP Weise müsste ich viel mehr schreiben code, der bedeutet mehr Chancen für Fehler, die auftreten...

Gibt es irgendwelche Bibliotheken, die in PHP, stellt datetime Betrieb in einer Weise, die nicht erfordern eine Menge code?beats sql in einer situation, wo " zwei Datumsangaben wie viele Arbeitstage gibt es zwischen zwei Terminen?Implementieren Sie entweder in SQL oder $pet_lang' ist dieses Problem gelöst, indem Sie diese Abfrage?

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;
War es hilfreich?

Lösung

PHP5 + 's Datetime-Objekt ist nützlich, weil es Sprung Zeit und Sommer bewusst, aber es braucht eine gewisse Erweiterung wirklich das Problem lösen. Ich schrieb folgend ein ähnliches Problem zu lösen. Die find_WeekdaysFromThisTo () -Methode ist Brute-Force, aber es funktioniert ziemlich schnell, wenn Ihre Zeitspanne weniger als 2 Jahren.

$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

Andere Tipps

Während für die meisten Operationen Datetime würde ich normalerweise auf Unix-Zeit umwandeln und zusätzlich Subtraktion usw. auf der Unix-Zeit integer durchführen, können Sie auf dem Zend Framework Zend_Date Klasse suchen.

Das hat viel von der Funktionalität, die Sie beschreiben. Obwohl Zend als „Rahmen“ in Rechnung gestellt wird es funktioniert besonders gut als eine Klassenbibliothek zu holen und wählten Elemente aus. Wir sind es routinemäßig in Projekten und ziehen Sie dann nur in Bits, wie und wann wir sie brauchen.

strtotime () ist nützlich, aber es hat einige seltsame Verhaltensweisen haben, die von Zeit zu Zeit Pop-up, wenn Sie nicht nur verwenden es eine formatierte Datum / Zeit-String zu konvertieren.

Dinge wie „1 Monat“ oder „-3 Tage“ kann man manchmal nicht geben, was du es Ausgang erwarten.

Für ein Datum Hinzufügen Sie die Methode verwenden können Datetime :: hinzufügen ( Fügt eine Anzahl von Tagen, Monaten, Jahren, Stunden, Minuten und Sekunden auf ein Datetime-Objekt ), erhältlich von pHP 5.3.0 ab.

, um die Differenz zwischen zwei Daten zu finden, gibt es die Datetime :: diff Methode; aber es scheint nicht ein Verfahren zum Zählen der Arbeitstage zwischen zwei Daten zu sein.

PEAR::Date sieht aus wie es könnte einige nützliche Funktionen haben.

PEAR::Calendar könnte auch nützlich sein.

Die einfachste Methode ist, einen Zeitstempel zu verwenden, die die Anzahl der Sekunden seit dem 1. Januar 2008 mit einem Zeitstempel Typ können Sie Dinge wie ...

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

Überprüfen Sie die Dokumentation aus für time () , date () und mktime () auf den pHP-Web-Seiten. Das sind die drei Methoden, die ich dazu neigen, die am häufigsten verwendet werden.

Sie können eine Kombination von strtotime , mktime und Datum das arithmetische todo

Hier ist ein Beispiel, das eine Combo todo verwendet einige Arithmetik http://rushi.wordpress.com/2008/04/13/php-print-out-age-of-date-in-words/ ich werde reproduzieren die Code hier der Einfachheit halber     

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

@Rushi Ich mag es nicht strtotime () persönlich .. Ich weiß nicht, warum, aber ich heute Morgen entdeckt, dass wie diese einen String übergeben ‚2008-09-11 9: 05.00‘ to strtotime ein false zurück. ..

Das glaube ich nicht der Code Sie das Beispiel Problem lösen ‚versehen, zwei Daten gegeben, wie viele Arbeitstage gibt es zwischen den beiden Daten? Implementieren Sie entweder in SQL oder $ pet_lang‘und ich habe nicht beachten, wenn ich eine Liste der Feiertag haben ...

Sie können Anzahl der Tage zwischen zwei Daten wie diese:

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

Und können Sie Funktion so etwas machen (ich habe nicht php in meinem Computer installiert, so dass ich nicht Syntax ist 100% richtig garantieren kann)

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

Wenn Sie nicht wie strtotime und haben Sie immer Datum in demselben Format, das Sie Funktion explodieren wie

verwenden können,
list($year, $month, day) = explode("-", $date);

ich empfehlen würde mit PHP 5.2 Datetime-Objekte , anstatt UNIX-Zeitstempel verwenden, wenn tun Datumsberechnungen. Wenn Sie die PHP Datumsfunktionen verwenden, die UNIX Zeit zurückkehrt, haben Sie eine sehr begrenzte Reichweite mit (vor 1970 zum Beispiel nichts) zu arbeiten.

Wenn Sie einen Blick auf http://php.net/date , finden Sie einige Beispiele finden die Verwendung mktime() Operationen auszuführen.

Ein einfaches Beispiel zu trainieren würde, was Datum Tomorrows wäre. Sie können das tun, indem Sie einfach 1 Hinzufügen zum Tageswert in mktime() wie folgt:

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

So, hier finden Sie ein Datum in Form YYYY-MM-DD enthält tomorrows Datum erhalten. Sie können auch Tage subtrahieren, indem Sie einfach mit ‚+‘ ersetzt ‚-‘. mktime() macht das Leben viel einfacher und erspart Ihnen, wenn Aussagen und andere störende Codierung zu tun verschachtelt.

bekommen Tage / Ferien arbeiten, postgresql CTE ftw - siehe http://osssmb.wordpress.com/2009/12/02/business-days-working-days-sql-for-postgres-2/

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top