Login   Register  
PHP Classes
elePHPant
Icontem

File: DateUtil.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Michiel de Roo  >  DateUtil  >  DateUtil.php  >  Download  
File: DateUtil.php
Role: Class source
Content type: text/plain
Description: class definitions
Class: DateUtil
Parsing, missing values, internationalization, etc
Author: By
Last change: added some extra functions.
- ability to handle missing information, like ??-08-2003
- setDate accepts shortcuts like tomorrow, next week, etc.
- fixed small bugs
- improved parsing algorithm
Date: 11 years ago
Size: 14,693 bytes
 

Contents

Class file image Download
<?
/*
* Class for handling data values in PHP
*
* This code provides classes for handling data values. 
* Features include format guess, internationalisation,  
* date calculattions, formatting.
* 
* If you write any additional translation files, please 
* send a copy to dateutil@mderoo.nl and I will add it to
* the repository
*
* Language files contributed by:
*
* English, Dutch, German: Michiel de Roo
* French: Sylvain CÔME <scome@club-internet.fr>           
* Italian: Roberto Legname <legname@betam.it>             
* Greek: Tom Dionysiou <tom@united-hellas.com>            
* Spanish: José Miguel Santibáñez <jms@caos.cl>           
* Czech: Vratislav Cermak <kremik@centrum.cz>             
* Brazilian: Claudio Pereira <cpereira@websistemas.com.br>
* Polish: cyplo <cyplo@wp.pl>
* Norwegian: Sten Johnson <Sten.Johnson@no.thalesgroup.com>
* Finnish: taken from KronoClass 
* Japanese: taken from KronoClass 
* Indonesian: taken from KronoClass
* Danish: taken from ezPublish 
* Russian: taken from ezPublish 
* Argentinian: taken from ezPublish 
*
* Please note that some languages need special font types, like
* iso-8859-2 or hellenic, to be displayed correctly. 
* 
* Examples:
* See http://www.mderoo.nl/software/dateutil/example.php
*
* @author Michiel de Roo <michiel@belangrijk.nl>, http://www.mderoo.nl
* @copyright 2003, Michiel de Roo
* @license BSD
* @package DateUtil
* @version 1.2
*
*----------------------------------------------------------------------
* License: freeeware under BSD license
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU General Public License
* for more details.
*
* Released under GNU Public License v2.0, available
* at www.fsf.org.  The author hereby disclaims all
* warranties relating to this software, express or implied,
* including with no limitation any implied warranties of
* merchantability, quality performance, or fitness for a
* particular purpose. The author and their distributors
* shall not be liable for any special, incidental,
* consequential, indirect or similar damages due to loss
* of data, even if an agent of the author has been found
* to be the source of loss or damage. In no event shall the
* author's liability for any damages ever exceed the price
* paid for the license to use software, regardless of the
* form of the claim. The person using the software bears all
* risk as to the quality and performance of the software.
*
* This software program, documentation, accompanying
* written and disk-based notes and specifications, and all
* referenced and related program files, screen display
* renditions, and text files, are the property of the
* author.
*
* The authors have done their best to insure that the
* material found in this document is both useful and
* accurate. However, please be aware that errors may exist,
* the author does not make any guarantee concerning the
* accuracy of the information found here or in the uses
* to which it may be put.
*
*----------------------------------------------------------------------
*
*/


?>
<?
/** Class that converts a date to a timestamp, using a smart parser to guess the format */
class BasicDate
{
	var $date = null;
	var $timestamp = null;
	var $missing = array();
	var $debug=false;
	
	/** Constructor */
	function BasicDate()
	{
		if($this->debug) trigger_error('Constructing BasicDate');
		$this->timestamp = mktime();
	}
	
	/** Sets the date to be parsed */
	function setDate($date=null)
	{
		if($this->debug) trigger_error('setDate '.$date);
		if($date==null || $date=="now") $date = date("Y-m-d H:i:s", mktime()); 
		$this->date = $date;
		BasicDate::execute(); //non-virtual
		return $this->execute(); //virtual
	}
	
	/** Starts parsing */ 
	function execute()
	{
		if($this->debug) trigger_error('execute');
		$this->missing = array();
		
		if($this->date==null) return;
		
		$a = preg_split("/[^0-9|:|\?]/",$this->date);
		if(count($a)==1) {  //unix timestamp
			if(ereg(":", $a[0])) return $this->setTime($a[0]);
			else $this->timestamp = $a[0]; return $this->timestamp;	
		}
		if(count($a)==2) { $a[2]=date("Y", mktime()); } //no year is given, using current
		if($a[0]>31) { $y=$a[0]; $m=$a[1]; $d=$a[2]; } //YYYY-MM-DD
		else { $y=$a[2]; $m=$a[1]; $d=$a[0]; } //DD-MM-YYYY
		
		if($m!="??") if($m>12) { $t=$d; $d=$m; $m=$t; } //unlikely case of "MM-DD-YYYY" or "YYYY-DD-MM"
		if($y!="??") if($y<100) $y+=2000; //case of "DD-MM-YY"
		
		if(count($a)>3) { //time is set
			if(ereg(":", $a[3])) { 
				$t = explode(":", $a[3]);
				if(count($t)>0) if($t[0]!="??") { $h = $t[0]; }
				if(count($t)>1) if($t[1]!="??") { $i = $t[1]; }
				if(count($t)>2) if($t[2]!="??") { $s = $t[2]; }
			}
		}
		
		if(!$h) { $h=0; $this->missing["h"] = true; } 
		if(!$i) { $i=0; $this->missing["i"] = true; } 
		if(!$s) { $s=0; $this->missing["s"] = true; } 
		if($m=="??") { $m=1; $this->missing["m"] = true; } 
		if($d=="??") { $d=1; $this->missing["d"] = true; } 
		if($y=="??") { $y=0; $this->missing["y"] = true; } 
		
		$this->timestamp = date("U", mktime($h+0,$i+0,$s+0,$m+0,$d+0,$y+0));
		if($this->debug) { 
			trigger_error('values '.$y." ".$m." ".$d." ".$h." ".$i." ".$s." ");
			trigger_error('missing ->');
			print_r($this->missing); echo "<br>\n";
		}
		return $this->timestamp;
	}
	
	function setTime($time)
	{
		$t = preg_split("/[^0-9|\?]/",$this->date);
		if(count($t)>0) if($t[0]!="??") { $h = $t[0]; }
		if(count($t)>1) if($t[1]!="??") { $i = $t[1]; }
		if(count($t)>2) if($t[2]!="??") { $s = $t[2]; }

		if(!$h) { $h=0; $this->missing["h"] = true; } 
		if(!$i) { $i=0; $this->missing["i"] = true; } 
		if(!$s) { $s=0; $this->missing["s"] = true; } 
		$m=1; $this->missing["m"] = true;
		$d=1; $this->missing["d"] = true;
		$y=0; $this->missing["y"] = true;		

		$this->timestamp = date("U", mktime($h+0,$i+0,$s+0,$m+0,$d+0,$y+0));
		if($this->debug) { 
			trigger_error('values '.$y." ".$m." ".$d." ".$h." ".$i." ".$s." ");
			trigger_error('missing ->');
			print_r($this->missing); echo "<br>\n";
		}
		return $this->timestamp;
	}
	
	/** Returns the Unix timestamp represented by this date */
	function getTimestamp()
	{
		return $this->timestamp;	
	}
	
	/** Sets the Unix timestamp to be represented by this date */
	function setTimestamp($t)
	{
		if($this->debug) trigger_error('setTimeStamp');
		$this->timestamp = $t;
		return $this->execute();
	}
}
?>
<?

/** Add and subtract periods */
class DateCalculator extends FormattedDate
{
	/** We overrride setDate to add some useful constants */
	function setDate($date=null, $format=null)
	{
		if($this->debug) trigger_error('setDate '.$date);
		switch($date) {
			case "today" : { $this->setDate(); }
			
			case "tomorrow" : { $this->setDate("now"); $this->add(1, "day"); break; }
			case "next week" : { $this->setDate(); $this->add(1, "week"); break; } 
			case "next month" : { $this->setDate(); $this->add(1, "month"); break; } 
			case "next year" : { $this->setDate(); $this->add(1, "year"); break; } 
			
			case "yesterday" : { $this->setDate("now"); $this->subtract(1, "day"); break; }
			case "last week" : { $this->setDate(); $this->subtract(1, "week"); break; } 
			case "last month" : { $this->setDate(); $this->subtract(1, "month"); break; } 
			case "last year" : { $this->setDate(); $this->subtract(1, "year"); break; } 
	
			default: return FormattedDate::setDate($date, $format); //non-virtual
		}
		return $this->execute(); //virtual
	}

	/** if $date2 is null, returns whether the the date represented by the current instance is smaller than the date given as the argument. If $date is not null, returns whether the first argument is smaller than the second. */
	function lt($date, $date2=null)
	{
		$a = $this->_comp($date, $date2);
		return $a[0] < $a[1];
	}
	
	function lte($date, $date2=null)
	{
		$a = $this->_comp($date, $date2);
		return $a[0] <= $a[1];
	}

	/** if $date2 is null, returns whether the the date represented by the current instance is greater than the date given as the argument. If $date is not null, returns whether the first argument is greater than the second. */
	function gt($date, $date2=null)
	{
		$a = $this->_comp($date, $date2);
		return $a[0] > $a[1];
	}
	
	function gte($date, $date2=null)
	{
		$a = $this->_comp($date, $date2);
		return $a[0] >= $a[1];
	}

	function _comp($date, $date2=null)
	{
		if($date2!=null) { 
			$this->setDate($date);
			$du2 = new DateUtil();
			$du2->setDate($date2);
		} else {
			$du2 = new DateUtil();
			$du2->setDate($date);
		}
		$a[0] = $this->getTimestamp();
		$a[1] = $du2->getTimestamp();
		
		return $a;
	}
	

	/** Adds amount of type (year, month, week, day, hour, minute, second) */
	function add($amount, $type="second")
	{
		if($this->debug) trigger_error('add '.$amount.' '.$type);
		
		if($type=="month") $this->_month($amount);
		if($type=="year") $this->_year($amount);

		$this->timestamp = $this->timestamp + $this->_sec($amount, $type);
		$this->date=null;
		return $this->execute();
	}
	
	/** Subtracts amount of type (year, month, week, day, hour, minute, second) */
	function subtract($amount, $type="second")
	{
		if($this->debug) trigger_error('subtract '.$amount.' '.$type);

		if($type=="month") $this->_month($amount);
		if($type=="year") $this->_year($amount);

		$this->timestamp += $this->_sec(-$amount, $type);
		$this->date=null;
		return $this->execute();
	}
	
	function _year($amount) 
	{
		$yy = date("Y", $this->timestamp)+$amount;
		$tt = date("$yy-m-d H:i:s", $this->timestamp);
		$this->setDate($tt);
		return;
	}
	function _month($amount) 
	{
		if($amount>=0) $sign=+1;
		else $sign=-1;
		$amount = abs($amount);
		
		$yy = date("Y", $this->timestamp);
		$mm = date("m", $this->timestamp)+$sign*$amount;
		while(abs($mm)>=12) {
			$mm-=$sign*12;
			$yy+=$sign;
		}
		$tt = date("$yy-$mm-d H:i:s", $this->timestamp);
		$this->setDate($tt);
		return;
	}
	//private, returns diff in seconds
	function _sec($amount, $type)
	{
		$mod = $amount;
		switch($type) {
			case "week" : $mod = $mod*7; 
			case "day" : $mod = $mod*24; 
			case "hour" : $mod = $mod*60; 
			case "minute" : $mod = $mod*60;  
		}
		return $mod;
	}	
}

?>
<?
//returns the date in a specific format
class FormattedDate extends BasicDate
{
	var $format = "Y-m-d";
	
	function setDate($date=null, $format=null)
	{
		if($this->debug) trigger_error('setDate '.$date);
		if($format!=null) { 
			$this->old_format = $this->format;
			$this->format = $format;
		}
		return BasicDate::setDate($date);
	}
	
	/** Sets the format to use */
	function setFormat($format)
	{
		if($this->debug) trigger_error('setFormat');
		$this->format = $format;
		return $this->execute();
	}
	
	/** Returns the formatted date */
	function execute()
	{
		if($this->debug) trigger_error('execute');
		$this->missing_format = $this->format;
		foreach($this->missing as $k=>$v) {
			if($k=="h") $this->missing_format = ereg_replace("[g|G|h|H]+", "??", $this->missing_format);
			if($k=="i") $this->missing_format = ereg_replace("[i]+", "??", $this->missing_format);
			if($k=="s") $this->missing_format = ereg_replace("[s]+", "??", $this->missing_format);
			
			if($k=="y") $this->missing_format = ereg_replace("[Y|y]+", "??", $this->missing_format);
			if($k=="m") $this->missing_format = ereg_replace("[F|j|M|m|n]+", "??", $this->missing_format);
			if($k=="d") $this->missing_format = ereg_replace("[d|j]+", "??", $this->missing_format);
			
			if($k=="y" | $k=="m" | $k=="d") 
				$this->missing_format = ereg_replace("[D|l|w]+ +", "", $this->missing_format);
		}
		if($this->debug) trigger_error('format '.$this->format);
		if($this->debug) trigger_error('missing_format '.$this->missing_format);
		return date($this->missing_format, $this->timestamp);	
		
	}
}

?>
<?

// performs internationalization on the format through configuration files 
class InternationalDate extends DateCalculator
{
	var $language = "en";	

	var $day = array();
	var $month = array();

	function InternationalDate()
	{
		if($this->debug) trigger_error('Constructing InternationalDate');
		BasicDate::BasicDate();
		$this->setLanguage($this->language);
	}
	
	/** Sets the language to use, this language must be present as the configuration file $language.cfg */
	function setLanguage($language)
	{
		if($this->debug) trigger_error('setLanguage: '.$language);
		$this->language = $language;
		
		$path = dirname(__FILE__);
		$file = "$path/$language.cfg";
		
		$fp = fopen($file, "r");
		$data = fread($fp, filesize($file));
		
		$lines = explode("\n", $data);
	
		$j=0;
		
		for($i=0; $i<7; $i++) {
			$l = explode(" ", $lines[$j++]);
			$this->day[$i] = $l[1];
		}
		$j++;
		
		for($i=0; $i<7; $i++) {
			$l = explode(" ", $lines[$j++]);
			$this->day_short[$i] = $l[1];
		}
		$j++;
		
		for($i=0; $i<12; $i++) {
			$l = explode(" ", $lines[$j++]);
			$this->month[$i] = $l[1];
		}
		$j++;

		for($i=0; $i<12; $i++) {
			$l = explode(" ", $lines[$j++]);
			$this->month_short[$i] = $l[1];
		}
		
		return $this->execute();
	}	
	
	/** Returns the translated date */
	function execute()
	{
		if($this->debug) trigger_error('execute()');
		FormattedDate::execute();
		
		$translated_format = str_replace( 'D','##1', $this->missing_format ); // $translated_day_short
		$translated_format = str_replace( 'l','##2', $translated_format ); // $translated_day
		$translated_format = str_replace( 'M','##3', $translated_format ); // $translated_month_short
		$translated_format = str_replace( 'F','##4', $translated_format ); // $translated_month  
		
		$d = date( 'w', $this->timestamp ) + 0;
		$translated_day   = $this->day[ $d ] ;
		$translated_day_short  = $this->day_short[ $d ];
		
		$m = date( 'm', $this->timestamp ) + 0;
		$translated_month = $this->month[ $m-1 ] ;
		$translated_month_short=  $this->month_short[ $m-1 ] ;

		$translated_string = str_replace( '##1',$translated_day_short, date( $translated_format, $this->timestamp ) );
		$translated_string = str_replace( '##2',$translated_day, $translated_string );
	
		$translated_string = str_replace( '##3',$translated_month_short, $translated_string );
		$translated_string = str_replace( '##4',$translated_month, $translated_string );
		
		if($this->old_format) $this->format = $this->old_format;
		BasicDate::execute();
		return $translated_string;
	}
}

/** This is just a wrapper that is always the sub-most class in the hierarchy. It provides all the functionality. */
class DateUtil extends InternationalDate
{
		
}


?>