php.de

Zurück   php.de > Webentwicklung > PHP Einsteiger

PHP Einsteiger PHP Problemlösungen für Spracheinsteiger
Archive: 2004, 2004/2, 2005, 2005/2, 2006, 2007, 2008, 2009, 2010,

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 23.01.2012, 11:06  
Neuer Benutzer
 
Registriert seit: 14.03.2008
Beiträge: 27
zeusel befindet sich auf einem aufstrebenden Ast
Standard Werktage hinzuaddieren

Hallo Ihr,

eine Frage: ich will in einem Script 10 Werktage zu einem bestimmten Datum hinzuaddieren dies mache ich wie folgt:
PHP-Code:
$day "$bestellung_jahr-$bestellung_monat-$bestellung_tag";
$nextDay strtotime("+10 day"strtotime($day));
$btb_termin date("Y-m-d"$nextDay);
echo 
"<p>BTB-Termin Tag: $btb_termin</p>"
SO weit so gut...funktioniert auch ordentlich nur sind derzeit ja auch die Samstage und Sonntage mit inbegriffen. Kann man diese Funktion erweitern, dass das hinzurechnen nur auf die Wochentage erfolgt? Gibt es da vielleicht auch eine Funktion?
zeusel ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 23.01.2012, 11:12  
Erfahrener Benutzer
 
Registriert seit: 22.01.2005
Beiträge: 606
Connar befindet sich auf einem aufstrebenden Ast
Standard

Erstes Ergebnis bei Google:

http://www.php.de/php-tipps-2009/538...-addieren.html ([Erledigt] Werktage zu einem Datum addieren)


MFG Connar
Connar ist offline   Mit Zitat antworten
Alt 23.01.2012, 11:30  
fab
Erfahrener Benutzer
 
Benutzerbild von fab
 
Registriert seit: 28.07.2010
Beiträge: 2.308
PHP-Kenntnisse:
Fortgeschritten
fab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblick
Standard

Dort wird allerdings überall davon ausgegangen, dass jeder Tag 86400 Sekunden hat, den Fehler solltest du nicht machen.

Eigene Funktionen brauchst du aber auch gar nicht. Hier steht, was strtotime alles kann
PHP-Code:
strtotime("+10 weekdays"); 
fab ist offline   Mit Zitat antworten
Alt 23.01.2012, 16:01  
Benutzer
 
Registriert seit: 04.03.2008
Beiträge: 59
stevezi befindet sich auf einem aufstrebenden Ast
Standard

wozu?
ich gehe mal davon aus, dass du das für ein Bestellsystem brauchst.
was machst du mit den Feiertagen?
mach doch einfach den Hinweis, dass die Bearbeitung ca. 10 Werktage in Anspruch nimmt.
stevezi ist offline   Mit Zitat antworten
Alt 23.01.2012, 16:32  
Erfahrener Benutzer
 
Benutzerbild von fireweasel
 
Registriert seit: 20.03.2010
Beiträge: 474
PHP-Kenntnisse:
Fortgeschritten
fireweasel ist ein Lichtblickfireweasel ist ein Lichtblickfireweasel ist ein Lichtblickfireweasel ist ein Lichtblickfireweasel ist ein Lichtblick
fireweasel eine Nachricht über ICQ schicken fireweasel eine Nachricht über AIM schicken fireweasel eine Nachricht über Yahoo! schicken fireweasel eine Nachricht über Skype™ schicken
Standard

Zitat:
Zitat von zeusel Beitrag anzeigen
Hallo Ihr,

eine Frage: ich will in einem Script 10 Werktage zu einem bestimmten Datum hinzuaddieren ...

... nur sind derzeit ja auch die Samstage und Sonntage mit inbegriffen.
*korinthenkack*

Der Samstag ist ein Werktag. Damit wird die "weekday"-Rechnung nicht funktionieren. Die kennt nur die im englischsprachigen Raum üblichen Arbeitstage ("working days" oder "business days") und hat von deutschen (bundesweiten und landesspezifischen) Feiertagsregelungen nicht die leiseste Ahnung.

Zitat:
Kann man diese Funktion erweitern, dass das hinzurechnen nur auf die Wochentage erfolgt? Gibt es da vielleicht auch eine Funktion?
Es gibt fertige Tabellen für jedes Jahr, und Tools die solche Fristen berechnen können, bspw.: http://www.datumsrechner.de/

Eine fertige Funktion dafür hat PHP bisher nicht. Java schon. Die Berechnungsbeispiele zeigen, dass die Sache nicht so trivial ist, wie man sich das gemeinhin vorstellt.

Damit das nicht zu negativ klingt, hier noch etwas Konstruktives: Ich missbrauche preg_match() als Werktagszähler. Was Arbeitstage sind, ist weitesgehend frei einstellbar und die Berechnung funktioniert auch über Jahres-Grenzen hinweg.

Wer die Klasse um eigene oder landesspezifische Feiertage erweitern möchte, überschreibt in einer vererbten Variante einfach die Funktion ::holidays().

Die etwas umständlichen Datums-Format-Wandlungen sind der Tatsache geschuldet, dass ich (bis auf die Schaltjahres-Berechnung) nur die in PHP eingebauten Datumsfunktionen benutzt habe. Die ursprüngliche Variante, die nur mit Jahr und Tagesnummer rechnet, kam ohne Umwandlungen aus. Dafür sind Ein- und Ausgabeformat jetzt flexibler.

PHP-Code:
class simple_day_skipper {

    
/// basic date calculations using mkdate(), strtotime(), idate()

    /// calculate day of the week for the given year-month-day
    /// return int(0...6) 0 MON ... 6 SAT
    
static function day_of_the_week(
        
$y,
        
$m,
        
$d 1
    
) {
        return 
is_int($dotw idate('w'mktime(000$m$d$y)))
            ? 
$dotw null;
    }

    
/// convert given string to year + daynum (1...3666)
    /// return array($year, $daynum) | null()
    
static function daynum(
        
$date /// str() see strtotime() for accepted formats
    
) {
        if (!
is_int($tstamp strtotime($date))) {
            return 
null;
        }
        return array (
            
idate('Y'$tstamp),
            
idate('z'$tstamp) + 
            
// the daynum from idate() seems to be 0-based
        
);
    }

    static function 
leap_year($year) {
        return (
$year || (!== $year 400) && (=== $year 100)) 
            ? 
1;
    }

    
/// create a list of holidays
    /// return list() of int(1...366)
    
static function holidays($year) {
        
$leap self::leap_year($year);
        
// easter_days() returns number of days after MAR/21st (dunno why)
        
$easter easter_days($year) + 81 $leap;
        return array (
            
// (DE) bundesweite Feiertage
            // on fixed day
            
1// JAN/1st
            
121 $leap// MAY/1st
            
276 $leap// OCT/3rd
            
359 $leap// DEC/25th
            
360 $leap,  // DEC/26th

            // relative to easter sunday
            
$easter 2// easter: FRI
            
$easter// easter: SUN
            
$easter 1// easter: MON
            
$easter 49// pentecost: SUN
            
$easter 50// pentecost: MON
        
);
    }

    
/// create a year as a sequence of bytes
    /// return str(binary) year as sequence of bytes
    
static function year_as_binary(
        
$year /// int()
    
) {
        
$days_in_year 365 self::leap_year($year);
        if (!
is_int($dotw_jan_1st self::day_of_the_week($year11))) {
            return 
null;
        }
        
$tmpl str_repeat("\x00\x01\x02\x03\x04\x05\x06"55);
        
$y substr($tmpl$dotw_jan_1st$days_in_year);
        
// mark holidays
        
foreach (self::holidays($year) as $daynum) {
            
$daynum -= 1// daynum is 1-based, string offsets are 0-based
            
$y[$daynum] = chr(ord($y[$daynum]) - 7);
        }
        return 
$y;
    }


    
/// the simple_day_skipper object

    /// constructor
    /// return -
    
function __construct() {
        
$this->fmt_output null;
        
$this->format();
        
$this->pcre null;
        
$this->working_days();
        return;
    }

    
/// set range of working days (invalid values get ignored)
    /// return $this
    
function working_days(
        
$a 1/// int(0...6) defaults to 1 (MON)
        
$b 5  /// int(0...6) defaults to 5 (FRI)
    
) {
        foreach (
$args = array ($a$b) as $val) {
            if (!
is_int($val) || $val || $val 6) {
                return 
$this;
            }
        }
        
sort($args); // need the lower one 1st
        
$this->pcre vsprintf('\x%02x-\x%02x'$args);
        
//return sscanf($this->pcre, '\x%d-\x%d');
        
return $this;
    }

    
/// set output-format.  invalid values get ignored.
    /// return $this
    
function format(
        
$fmt null // see strfttime() for allowed format templates
    
) {
        
$this->fmt_output is_string(strftime($fmt))
            ? 
$fmt
            
'%Y-%m-%d'// ISO date format
        
return $this;
    }


    
/// skip the given amount of working days and get the target date
    /// return str() strftime()-formatted target date
    
function skip_days(
        
$basedate/// str() see strtotime() for allowed formats
        
$daydiff /// int(1...) number of working-days to skip
    
) {
        if (!
is_array(list ($year$daynum) = $this->daynum($basedate))) {
            return 
null;
        }
         while (
is_string($y self::year_as_binary($year))) {
            
preg_match(
                
// {0,%d} is for years which end with non-working-days
                
sprintf(
                    
'/(?:[^%s]*[%s]|[^%s]*\z){0,%d}/'
                    
$this->pcre$this->pcre$this->pcre$daydiff
                
),
                
$y$hnull$daynum 
                
// string offsets are 0-based, 
                // but we start counting at the next day
            
);
            if (
$daynum strlen($h[0]) < strlen($y)) {                
                break;
            }
            
// end of current year reached
            
$daydiff -= strlen(
                
preg_replace(sprintf('/[^%s]+/'$this->pcre), ''$h[0])
            );
            if (
=== $daydiff) {
                break;
            }
            
$daynum 1// 1st day in next year
            
++$year;
            
//break;
        
}
        return 
is_int($tstamp strtotime(
            
// PostGreSQL format YYYY.DDD (day is 1-based)
            
sprintf('%04d.%03d'$year$daynum strlen($h[0]))
        ))
            ? 
strftime($this->fmt_output$tstamp)
            : 
null;
    }

Ein paar Tests zeigen die Anwendung:

PHP-Code:
$tests = array (
    array (
'2011-12-27'2),
    array (
'2011-12-28'2),
    array (
'2011-12-29'2),
    array (
'2011-12-30'2),
    array (
'2011-12-31'2),
    array (
'2012-01-01'2),
    array (
'2012-01-02'2),
);

$skippy = new simple_day_skipper();

// Ausgabeformat des Zieldatums festlegen:
$skippy->format('%Y %m %d');

// Wir zaehlen Arbeitstage, also Montag (1) bis Freitag (5) 
$skippy->working_days(15);

foreach (
$tests as $test) {
    list (
$base_date$days_to_skip) = $test;

    
$target_date $skippy->skip_days($base_date$days_to_skip);

    
printf("%s + %s => %s\r\n"$base_date$days_to_skip$target_date);
}

// das Gleiche mit Werktagen: Montag bis Samstag (6)
$skippy->working_days(1,6);

foreach (
$tests as $test) {
    list (
$base_date$days_to_skip) = $test;

    
$target_date $skippy->skip_days($base_date$days_to_skip);

    
printf("%s + %s => %s\r\n"$base_date$days_to_skip$target_date);


Geändert von fireweasel (25.01.2012 um 15:52 Uhr). Grund: typos, ergänzungen, simple_day_skipper
fireweasel ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Datum berechnen unter Berücksichtigung der Werktage FRAD PHP Tipps 2009 3 07.09.2009 12:27
[Erledigt] Werktage zu einem Datum addieren Curcio PHP Tipps 2009 10 06.04.2009 18:28
[Erledigt] Eine Stunde hinzuaddieren, wie? &lt;gespeicherte Zeit miskam PHP Tipps 2009 40 11.01.2009 02:18
Problem und Frage zu Listenfeldauswertung .... bp158 PHP Tipps 2006 2 10.07.2006 22:37
werktage eines zeitraumes zusammenzählen Crypi PHP Tipps 2005 2 01.04.2005 15:42

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
php datum werktage addieren, postgresql werktage berechnen, fertige tabelle werktage, java datum addiere werktage, php strtotime mit werktagen, strtotime werktage, next werktag php, strtotime werktag, php strtotime weekdays, php werktage addieren, php werktage

Alle Zeitangaben in WEZ +2. Es ist jetzt 21:35 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum