User Tools

Site Tools


php:libraries:ydatetime

[PHP] YDateTime & YDateInterval Classes

DateTime und DateInterval sind zwar eine tolle Sache, jedoch fehlen mir gewisse Funktionalitäten. Dazu gehört das Runden in der DateTime genauso wie das bessere Arbeiten der Spezifikationsstrings im DateInterval

YDateTime Erweiterungen zu DateTime
  • round() Runden anhand eines DateInterval
  • round2() Runden anhand direkten Parametern
  • trunc() Abschneiden eines Datumteils
  • Ausgabe der Datumselemente ohne format. zB. echo $date→y;
YDateInterval Erweiterungen zu DateInterval
  • getSec() Berechnet die Intervalslänge in Sekunden
  • getSpecString() Gibt den Spezifikationsstring zurück (zB. P2DT5M)
  • getFullSpecString() Gibt den Spezifikationsstring inkl. 0-Werten zurück (zB. P0Y0M2DT0H5M0S)

YDateTime

YDateTime.php
/**
 * Erweiterungen zu DateTime:
 * - round()        Runden anhand eines DateInterval 
 * - round2()       Runden anhand direkten Parametern
 * - trunc()        Abschneiden eines Datumteils
 * - Ausgabe der Datumselemente ohne format
 */
class YDateTime extends DateTime{
	const KEY_YEAR      = 'y';
	const KEY_MONTH     = 'm';
	const KEY_DAY       = 'd';
	const KEY_HOUR      = 'h';
	const KEY_MINUTE    = 'i';
	const KEY_SECOND    = 's';
 
	protected $dateParts = array();
	protected $datePartsJson = <<<JSON
{
	"y":{"format":"Y", "zero":0, "part":"date", "string":"year"},
	"m":{"format":"n", "zero":1, "part":"date", "string":"month"},
	"d":{"format":"j", "zero":1, "part":"date", "string":"day"},
	"h":{"format":"G", "zero":0, "part":"time", "string":"hour"},
	"i":{"format":"i", "zero":0, "part":"time", "string":"minute"},
	"s":{"format":"s", "zero":0, "part":"time", "string":"second"}
}
JSON;
 
	/**
	 * @see DateTime::__construct
	 */
	public function __construct($time = "now", DateTimeZone $timezone = NULL){
		if($time instanceof DateTime) $time = $time->format('Y-m-d H:i:s');
		//Interne 'Variablen' definieren
		$this->dateParts = json_decode($this->datePartsJson, true);     
		parent::__construct($time, $timezone);        
	}
 
	/**
	 * Akzeptiert nur Einträge aus $formatJson
	 * @param $key: Alle KEY-Konstanten
	 * @throws Exception
	 */
	public function __get($key){
		if(array_key_exists($key, $this->dateParts)){
			return (int)$this->format($this->dateParts[$key]['format']);
		}else{
			throw new Exception("Property '{$key}' dosnt exists");
		}
	}
	/**
	 * Akzeptiert nur Einträge aus $formatJson
	 * @param $key: Alle KEY-Konstanten
	 * @param $value
	 * @throws Exception
	 */
	public function __set($key, $value){
		if(array_key_exists($key, $this->dateParts)){
			if($this->dateParts[$key]['part'] ==='date'){
				//Änderung im Datum
				parent::setDate(
						($key == self::KEY_YEAR)   ? $value : $this->y, 
						($key == self::KEY_MONTH)  ? $value : $this->m, 
						($key == self::KEY_DAY)    ? $value : $this->d);
			}elseif($this->dateParts[$key]['part'] ==='time'){
				//Änderung in der Zeit
				parent::setTime(
						($key == self::KEY_HOUR)   ? $value : $this->h, 
						($key == self::KEY_MINUTE) ? $value : $this->i, 
						($key == self::KEY_SECOND) ? $value : $this->s);
			}
		}else{
			throw new Exception("Property '{$key}' dosnt exists");
		}        
	}
 
 
	/**
	 * @see DateTime::createFromFormat
	 */
	public static function createFromFormat($format, $time, $timezone=null ){
		return new YDateTime(parent::createFromFormat($format, $time, $timezone));
	}
 
	/**
	 * rundet den Timestamp auf die Genauigkeit von DateInterval. 
	 * Es wird auf den ersten Eintrag im Interval gerundet. Alle
	 * weiteren werden ignoriert: PT1H15M rundet also auf 1 Stunde genau
	 * @todo    Runden auf Datum ist nicht so ganz durchdacht
	 * @param   DateInterval $delta
	 * @see round()
	 */
	public function round(DateInterval $delta, $mode = PHP_ROUND_HALF_UP){
		if(!($delta instanceof YDateInterval)) $delta = new YDateInterval($delta);
		//Richtiger Part aussuchen und runden
		foreach($this->dateParts as $key => $format) {
			if($delta->$key != 0){
				$this->$key = round( $this->$key / $delta->$key, 0, $mode) * $delta->$key;
				break;
			}
		}
		//Alles nachfolgende auf 0 setzen
		$this->trunc($key);
	}
 
 
	/**
	 * Runden ohne die DateInterval Klasse
	 * @param $key: Alle KEY-Konstanten
	 * @see round()
	 * @throws Exception
	 */
	public function round2($key, $precision, $mode = PHP_ROUND_HALF_UP){
		if(array_key_exists($key, $this->dateParts)){
			//Ein YDateInterval erstellen und $this->round() ausführen 
			$delta = YDateInterval::createFromDateString("{$precision} {$this->dateParts[$key]['string']}");
			$this->round($delta);
		}else{
			throw new Exception("Property '{$key}' dosnt exists");
		}
	}
 
	/**
	 * Abschneiden der weiteren Informationen.
	 * $date->trunc(YDateTime::KEY_DAY); schneidet alles nach dem Tag ab
	 * @param $key: Alle KEY-Konstanten
	 * @throws Exception
	 */
	public function trunc($key){
		if(array_key_exists($key, $this->dateParts)){
 
			$zeroFromNow = false;
			foreach($this->dateParts as $var => $format) {
				if(!$zeroFromNow && $key == $var){
					$zeroFromNow = true;
				}elseif($zeroFromNow){
					$this->$var = $format['zero'];
				}
			}  
		}else{
			throw new Exception("Property '{$key}' dosnt exists");
		}
	}
 
}

Beispiel zu YDateTime

Beispiel
define('C_TIME_FORMAT', 'd.m.Y H:i:s');
require_once 'YDateTime.php';
 
//Jetzt
$now = new YDateTime();
var_dump($now->format(C_TIME_FORMAT));
 
//round() auf 15 Minuten
$o = $now;
$o->round(New YDateInterval('PT15M'));
var_dump($o->format(C_TIME_FORMAT));
 
//round2() auf 20 Minuten
$o = $now;
$o->round2(YDateTime::KEY_MINUTE, 20);
var_dump($o->format(C_TIME_FORMAT));
 
//trunc() auf Tage
$o = $now;
$o->trunc(YDateTime::KEY_DAY);
var_dump($o->format(C_TIME_FORMAT));

Ausgabe

string(19) "01.10.2013 13:11:14"
string(19) "01.10.2013 13:15:00"
string(19) "01.10.2013 13:20:00"
string(19) "01.10.2013 00:00:00"

YDateInterval

YDateInterval.php
/**
 * Erweiterungen zu DateInterval:
 * - getSec()               Berechnet die Intervalslänge in Sekunden
 * - getSpecString()        Gibt den Spezifikationsstring zurück (zB. P2DT5M)
 * - getFullSpecString()    Gibt den Spezifikationsstring inkl. 0-Werten zurück (zB. P0Y0M2DT0H5M0S)
 */
class YDateInterval extends DateInterval{
 
	/**
	 * Konstrukteur
	 * $interval_spec kann entweder ein Spezifikationsstring sein oder ein
	 * DateInterval-Objekt.
	 * @param Variant
	 */
	public function __construct($interval_spec){
		//Falls es ein DateInterval ist, den $interval_spec auslesen
		if($interval_spec instanceof DateInterval) {
			$interval_spec = self::getStaticFullSpecString($interval_spec);
		}
		parent::__construct($interval_spec);
	}
 
	/**
	 * Erstellt ein YDateInterval aus einem normalen DateInterval
	 * @param DateInterval $delta
	 * @return YDateInterval
	 */
	static function createFromDateInterval(DateInterval $delta){
		return new YDateInterval(self::getStaticSpecString($delta));
	}
 
	/**
	 * Berechnet die Intervalslänge in Sekunden
	 * @return number
	 */
	function getSec(){
		return ($this->s)
		+ ($this->i * 60)
		+ ($this->h * 60 * 60)
		+ ($this->d * 60 * 60 * 24)
		+ ($this->m * 60 * 60 * 24 * 30)
		+ ($this->y * 60 * 60 * 24 * 365);
	}
 
	/**
	 * Gibt den lesbaren Spezifikationsstring zurück
	 * @exampe: 'P2DT5M'
	 * @return String
	 */
	public function getSpecString(){
		return self::getSpecString($this);
	}
 
	/**
	 * Gibt einen Spezifikationsstring zurück. Im gegensatz zu getSpecString()
	 * werden auch die Parameter mit angegeben die 0 sind. Um mit PHP zu arbeiten
	 * reicht dieser aus.
	 * @exampe: 'P0Y0M2DT0H5M0S'
	 * @return String
	 */
	public function getFullSpecString(){
		return self::getStaticFullSpecString($this);
	}
 
	/**
	 * statische Version von getSpecString um den String von einem DateInterval
	 * zu ermitteln
	 * @exampe: 'P0Y0M2DT0H5M0S'
	 * @param  DateInterval
	 * @return String
	 */
	public static function getStaticFullSpecString(DateInterval $delta){
		return $delta->format('P%yY%mM%dDT%hH%iM%sS');
	}
 
	/**
	 * statische Version von getFullSpecString um den String von einem DateInterval
	 * zu ermitteln
	 * @exampe: 'P2DT5M'
	 * @param  DateInterval
	 * @return String
	 */
	public static function getStaticSpecString(DateInterval $delta){
		//Read all date-parts there are not 0
		$date = array_filter(array('Y' => $delta->y, 'M' => $delta->m, 'D' => $delta->d));
		//Read all time-parts there are not 0
		$time = array_filter(array('H' => $delta->h, 'M' => $delta->i, 'S' => $delta->s));
 
		//Convert each part to spec-Strings
		foreach($date as $key => &$value) $value = $value.$key;
		foreach($time as $key => &$value) $value = $value.$key;
 
		//Create date spec-string
		$spec = 'P' . implode('', $date);
		//add time spec-string
		if(count($time)>0) $spec .= 'T' . implode('', $time);
		return $spec;
	}
}
php/libraries/ydatetime.txt · Last modified: 26.01.2022 23:40:31 by yaslaw