PageRenderTime 53ms CodeModel.GetById 26ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 1ms

/includes/qcodo/_core/framework/QDateTime.class.php

http://github.com/qcodo/qcodo
PHP | 812 lines | 524 code | 99 blank | 189 comment | 103 complexity | ebbf40821a870e1da9a94e3fe61ebc75 MD5 | raw file
  1<?php
  2	// These Aid with the PHP 5.2 DateTime error handling
  3	class QDateTimeNullException extends QCallerException {}
  4	function QDateTimeErrorHandler() {}
  5
  6	/**
  7	 * QDateTime (Standard)
  8	 * REQUIRES: PHP >= 5.2.0
  9	 * 
 10	 * This DateTime class manages datetimes for the entire system.  It basically
 11	 * provides a nice wrapper around the PHP DateTime class, which is included with
 12	 * all versions of PHP >= 5.2.0.
 13	 * 
 14	 * For legacy PHP users (PHP < 5.2.0), please refer to QDateTime.legacy
 15	 */
 16	class QDateTime extends DateTime {
 17		const Now = 'now';
 18		const FormatIso = 'YYYY-MM-DD hhhh:mm:ss';
 19		const FormatIsoCompressed = 'YYYYMMDDhhhhmmss';
 20		const FormatDisplayDate = 'MMM DD YYYY';
 21		const FormatDisplayDateFull = 'DDD, MMMM D, YYYY';
 22		const FormatDisplayDateTime = 'MMM DD YYYY hh:mm zz';
 23		const FormatDisplayDateTimeFull = 'DDDD, MMMM D, YYYY, h:mm:ss zz';
 24		const FormatDisplayTime = 'hh:mm:ss zz';
 25		const FormatRfc822 = 'DDD, DD MMM YYYY hhhh:mm:ss ttt';
 26
 27		// Note: RFC 5322 actually obsoletes RFC 2822, but both have the same date time format specification
 28		// Both constants are defined here just as a convenience
 29		const FormatRfc2822 = 'DDD, DD MMM YYYY hhhh:mm:ss ttttt';
 30		const FormatRfc5322 = 'DDD, DD MMM YYYY hhhh:mm:ss ttttt';
 31
 32		const FormatSoap = 'YYYY-MM-DDThhhh:mm:ss';
 33
 34		public static $DefaultFormat = QDateTime::FormatDisplayDateTime;
 35		public static $DefaultTimeOnlyFormat = QDateTime::FormatDisplayTime;
 36		public static $DefaultDateOnlyFormat = QDateTime::FormatDisplayDate;
 37
 38		/**
 39		 * Specify whether or not to perform Translation while doing a ToString() call
 40		 * @var boolean
 41		 */
 42		public static $Translate = false;
 43
 44		/**
 45		 * Returns a new QDateTime object that's set to "Now"
 46		 * Set blnTimeValue to true (default) for a DateTime, and set blnTimeValue to false for just a Date
 47		 *
 48		 * @param boolean $blnTimeValue whether or not to include the time value
 49		 * @return QDateTime the current date and/or time
 50		 */
 51		public static function Now($blnTimeValue = true) {
 52			$dttToReturn = new QDateTime(QDateTime::Now);
 53			if (!$blnTimeValue) {
 54				$dttToReturn->blnTimeNull = true;
 55				$dttToReturn->ReinforceNullProperties();
 56			}
 57			return $dttToReturn;
 58		}
 59
 60		protected $blnDateNull = true;
 61		protected $blnTimeNull = true;
 62
 63		public static function NowToString($strFormat = null) {
 64			$dttNow = new QDateTime(QDateTime::Now);
 65			return $dttNow->ToString($strFormat);
 66		}
 67		public function IsDateNull() {
 68			return $this->blnDateNull;
 69		}
 70		public function IsNull() {
 71			return ($this->blnDateNull && $this->blnTimeNull);
 72		}
 73		public function IsTimeNull() {
 74			return $this->blnTimeNull;
 75		}
 76		public function PhpDate($strFormat) {
 77			// This just makes a call to format
 78			return parent::format($strFormat);
 79		}
 80		public function GetSoapDateTimeArray($dttArray) {
 81			if (!$dttArray)
 82				return null;
 83
 84			$strArrayToReturn = array();
 85			foreach ($dttArray as $dttItem)
 86				array_push($strArrayToReturn, $dttItem->__toString(QDateTime::FormatSoap));
 87			return $strArrayToReturn;
 88		}
 89
 90		/**
 91		 * Constructs a new QDateTime from a integer-based timestamp value
 92		 * @param integer $intTimestamp
 93		 * @param DateTimeZone $objTimeZone
 94		 * @return QDateTime
 95		 */
 96		public static function FromTimestamp($intTimestamp, DateTimeZone $objTimeZone = null) {
 97			return new QDateTime(date('Y-m-d H:i:s', $intTimestamp), $objTimeZone);
 98		}
 99
100		/**
101		 * Constructs a new QDateTime as a time-only value.  Uses default QDateTime constructor
102		 * and simply nulls out the time value right afterward.
103		 * @param mixed $mixValue
104		 * @param DateTimeZone $objTimeZone
105		 * @return QDateTime
106		 */
107		public static function FromTimeOnly($mixValue = null, DateTimeZone $objTimeZone = null) {
108			$dttToReturn = new QDateTime($mixValue, $objTimeZone);
109			$dttToReturn->SetDate(null, null, null);
110			return $dttToReturn;
111		}
112
113		public function __construct($mixValue = null, DateTimeZone $objTimeZone = null) {
114			// Cloning from another QDateTime object
115			if ($mixValue instanceof QDateTime) {
116				if ($objTimeZone)
117					throw new QCallerException('QDateTime cloning cannot take in a DateTimeZone parameter');
118				if ($mixValue->GetTimeZone()->GetName() == date_default_timezone_get())
119					parent::__construct($mixValue->format('Y-m-d H:i:s'));
120				else
121					parent::__construct($mixValue->format(DateTime::ISO8601));
122				$this->blnDateNull = $mixValue->IsDateNull();
123				$this->blnTimeNull = $mixValue->IsTimeNull();
124
125			// Subclassing from a PHP DateTime object
126			} else if ($mixValue instanceof DateTime) {
127				if ($objTimeZone)
128					throw new QCallerException('QDateTime subclassing of a DateTime object cannot take in a DateTimeZone parameter');
129				parent::__construct($mixValue->format(DateTime::ISO8601));
130
131				// By definition, a DateTime object doesn't have anything nulled
132				$this->blnDateNull = false;
133				$this->blnTimeNull = false;
134
135			// Using "Now" constant
136			} else if (strtolower($mixValue) == QDateTime::Now) {
137				if ($objTimeZone)
138					parent::__construct('now', $objTimeZone);
139				else
140					parent::__construct('now');
141				$this->blnDateNull = false;
142				$this->blnTimeNull = false;
143
144			// Null or No Value
145			} else if (!$mixValue) {
146				// Set to "null date"
147				// And Do Nothing Else -- Default Values are already set to Nulled out
148				if ($objTimeZone)
149					parent::__construct('2000-01-01 00:00:00', $objTimeZone);
150				else
151					parent::__construct('2000-01-01 00:00:00');
152
153			// Parse the Value string
154			} else {
155				$intTimestamp = null;
156				$blnValid = false;
157				QApplication::SetErrorHandler('QDateTimeErrorHandler');
158				try {
159					if ($objTimeZone)
160						$blnValid = parent::__construct($mixValue, $objTimeZone);
161					else
162						$blnValid = parent::__construct($mixValue);
163				} catch (Exception $objExc) {}
164				if ($blnValid !== false)
165					$intTimestamp = parent::format('U');
166				QApplication::RestoreErrorHandler();
167
168				// Valid Value String
169				if ($intTimestamp) {
170					// To deal with "Tues" and date skipping bug in PHP 5.2
171					if ($objTimeZone)
172						parent::__construct(date('Y-m-d H:i:s', parent::format('U')), $objTimeZone);
173					else
174						parent::__construct(date('Y-m-d H:i:s', parent::format('U')));
175
176					// We MUST assume that Date isn't null
177					$this->blnDateNull = false;
178
179					// Update Time Null Value if Time was Specified
180					if (strpos($mixValue, ':') !== false)
181						$this->blnTimeNull = false;
182
183				// Timestamp-based Value string
184				} else if (is_numeric($mixValue)) {
185					if ($objTimeZone)
186						parent::__construct(date('Y-m-d H:i:s', $mixValue), $objTimeZone);
187					else
188						parent::__construct(date('Y-m-d H:i:s', $mixValue));
189
190					$this->blnTimeNull = false;
191					$this->blnDateNull = false;
192
193				// Null Date
194				} else {
195					// Set to "null date"
196					// And Do Nothing Else -- Default Values are already set to Nulled out
197					if ($objTimeZone)
198						parent::__construct('2000-01-01 00:00:00', $objTimeZone);
199					else
200						parent::__construct('2000-01-01 00:00:00');
201				}
202			}
203		}
204
205		/* The Following Methods are in place because of a bug in PHP 5.2.0 */
206		protected $strSerializedData;
207		public function __sleep() {
208			$this->strSerializedData = parent::format(DateTime::ISO8601);
209			return array('blnDateNull', 'blnTimeNull', 'strSerializedData');
210		}
211		public function __wakeup() {
212			parent::__construct($this->strSerializedData);
213		}
214
215		public function __toString() {
216			// For PHP 5.3 Compatability
217			$strArgumentArray = func_get_args();
218
219			if (count($strArgumentArray) >= 1)
220				$strFormat = $strArgumentArray[0];
221			else
222				$strFormat = null;
223
224			return $this->ToString($strFormat);
225		}
226
227		/**
228		 * Outputs the date as a string given the format strFormat.  By default,
229		 * it will return as QDateTime::FormatDisplayDate "MMM DD YYYY", e.g. Mar 20 1977.
230		 *
231		 * Properties of strFormat are (using Sunday, March 2, 1977 at 1:15:35 pm
232		 * in the following examples):
233		 *
234		 *	M - Month as an integer (e.g., 3)
235		 *	MM - Month as an integer with leading zero (e.g., 03)
236		 *	MMM - Month as three-letters (e.g., Mar)
237		 *	MMMM - Month as full name (e.g., March)
238		 *
239		 *	D - Day as an integer (e.g., 2)
240		 *	DD - Day as an integer with leading zero (e.g., 02)
241		 *	DDD - Day of week as three-letters (e.g., Wed)
242		 *	DDDD - Day of week as full name (e.g., Wednesday)
243		 *
244		 *	YY - Year as a two-digit integer (e.g., 77)
245		 *	YYYY - Year as a four-digit integer (e.g., 1977)
246		 *
247		 *	h - Hour as an integer in 12-hour format (e.g., 1)
248		 *	hh - Hour as an integer in 12-hour format with leading zero (e.g., 01)
249		 *	hhh - Hour as an integer in 24-hour format (e.g., 13)
250		 *	hhhh - Hour as an integer in 24-hour format with leading zero (e.g., 13)
251		 *
252		 *	mm - Minute as a two-digit integer
253		 *
254		 *	ss - Second as a two-digit integer
255		 *
256		 *	z - "pm" or "am"
257		 *	zz - "PM" or "AM"
258		 *	zzz - "p.m." or "a.m."
259		 *	zzzz - "P.M." or "A.M."
260		 *
261		 *  ttt - Timezone Abbreviation as a three-letter code (e.g. PDT, GMT)
262		 *  tttt - Timezone Identifier (e.g. America/Los_Angeles)
263		 *
264		 * @param string $strFormat the format of the date
265		 * @return string the formatted date as a string
266		 */
267		public function ToString($strFormat = null) {
268			$this->ReinforceNullProperties();
269			if (is_null($strFormat)) {
270				if ($this->IsTimeNull())
271					$strFormat = QDateTime::$DefaultDateOnlyFormat;
272				else if ($this->IsDateNull())
273					$strFormat = QDateTime::$DefaultTimeOnlyFormat;
274				else
275					$strFormat = QDateTime::$DefaultFormat;
276			}
277
278			preg_match_all('/(?(?=D)([D]+)|(?(?=M)([M]+)|(?(?=Y)([Y]+)|(?(?=h)([h]+)|(?(?=m)([m]+)|(?(?=s)([s]+)|(?(?=z)([z]+)|(?(?=t)([t]+)|))))))))/', $strFormat, $strArray);
279			$strArray = $strArray[0];
280			$strToReturn = '';
281
282			$intStartPosition = 0;
283			for ($intIndex = 0; $intIndex < count($strArray); $intIndex++) {
284				$strToken = trim($strArray[$intIndex]);
285				if ($strToken) {
286					$intEndPosition = strpos($strFormat, $strArray[$intIndex], $intStartPosition);
287					$strToReturn .= substr($strFormat, $intStartPosition, $intEndPosition - $intStartPosition);
288					$intStartPosition = $intEndPosition + strlen($strArray[$intIndex]);
289
290					switch ($strArray[$intIndex]) {
291						case 'M':
292							$strToReturn .= parent::format('n');
293							break;
294						case 'MM':
295							$strToReturn .= parent::format('m');
296							break;
297						case 'MMM':
298							$strToReturn .= (self::$Translate) ? QApplication::Translate(parent::format('M')) : parent::format('M');
299							break;
300						case 'MMMM':
301							$strToReturn .= (self::$Translate) ? QApplication::Translate(parent::format('F')) : parent::format('F');
302							break;
303			
304						case 'D':
305							$strToReturn .= parent::format('j');
306							break;
307						case 'DD':
308							$strToReturn .= parent::format('d');
309							break;
310						case 'DDD':
311							$strToReturn .= (self::$Translate) ? QApplication::Translate(parent::format('D')) : parent::format('D');
312							break;
313						case 'DDDD':
314							$strToReturn .= (self::$Translate) ? QApplication::Translate(parent::format('l')) : parent::format('l');
315							break;
316			
317						case 'YY':
318							$strToReturn .= parent::format('y');
319							break;
320						case 'YYYY':
321							$strToReturn .= parent::format('Y');
322							break;
323			
324						case 'h':
325							$strToReturn .= parent::format('g');
326							break;
327						case 'hh':
328							$strToReturn .= parent::format('h');
329							break;
330						case 'hhh':
331							$strToReturn .= parent::format('G');
332							break;
333						case 'hhhh':
334							$strToReturn .= parent::format('H');
335							break;
336
337						case 'mm':
338							$strToReturn .= parent::format('i');
339							break;
340			
341						case 'ss':
342							$strToReturn .= parent::format('s');
343							break;
344			
345						case 'z':
346							$strToReturn .= parent::format('a');
347							break;
348						case 'zz':
349							$strToReturn .= parent::format('A');
350							break;
351						case 'zzz':
352							$strToReturn .= sprintf('%s.m.', substr(parent::format('a'), 0, 1));
353							break;
354						case 'zzzz':
355							$strToReturn .= sprintf('%s.M.', substr(parent::format('A'), 0, 1));
356							break;
357
358						case 'ttt':
359							$strToReturn .= parent::format('T');
360							break;
361						case 'tttt':
362							$strToReturn .= parent::format('e');
363							break;
364						case 'ttttt':
365							$strToReturn .= parent::format('O');
366							break;
367
368						default:
369							$strToReturn .= $strArray[$intIndex];
370					}
371				}
372			}
373
374			if ($intStartPosition < strlen($strFormat))
375				$strToReturn .= substr($strFormat, $intStartPosition);
376
377			return $strToReturn;
378		}
379
380		public function format($strFormat) {
381			$this->ReinforceNullProperties();
382			return parent::format($strFormat);
383		}
384
385		public function setTime($intHour, $intMinute, $intSecond = null) {
386			// For compatibility with PHP 5.3
387			if (is_null($intSecond)) $intSecond = 0;
388
389			// If HOUR or MINUTE is NULL...
390			if (is_null($intHour) || is_null($intMinute)) {
391				parent::setTime($intHour, $intMinute, $intSecond);
392				$this->blnTimeNull = true;
393				return $this;
394			}
395
396			$intHour = QType::Cast($intHour, QType::Integer);
397			$intMinute = QType::Cast($intMinute, QType::Integer);
398			$intSecond = QType::Cast($intSecond, QType::Integer);
399
400			if (is_null($intHour))
401				$this->blnTimeNull = true;
402			else
403				$this->blnTimeNull = false;
404
405			parent::setTime($intHour, $intMinute, $intSecond);
406			return $this;
407		}
408
409		public function setDate($intYear, $intMonth, $intDay) {
410			$intYear = QType::Cast($intYear, QType::Integer);
411			$intMonth = QType::Cast($intMonth, QType::Integer);
412			$intDay = QType::Cast($intDay, QType::Integer);
413
414			if (is_null($intYear))
415				$this->blnDateNull = true;
416			else
417				$this->blnDateNull = false;
418
419			parent::setDate($intYear, $intMonth, $intDay);
420			return $this;
421		}
422
423		protected function ReinforceNullProperties() {
424			if ($this->blnDateNull)
425				parent::setDate(2000, 1, 1);
426			if ($this->blnTimeNull)
427				parent::setTime(0, 0, 0);
428		}
429		
430		/**
431		 * Converts the current QDateTime object to a different TimeZone.
432		 * 
433		 * TimeZone should be passed in as a string-based identifier.
434		 * 
435		 * Note that this is different than the built-in DateTime::SetTimezone() method which expicitly
436		 * takes in a DateTimeZone object.  QDateTime::ConvertToTimezone allows you to specify any
437		 * string-based Timezone identifier.  If none is specified and/or if the specified timezone
438		 * is not a valid identifier, it will simply remain unchanged as opposed to throwing an exeception
439		 * or error.
440		 * 
441		 * @param string $strTimezoneIdentifier a string-based parameter specifying a timezone identifier (e.g. America/Los_Angeles)
442		 * @return void
443		 */
444		public function ConvertToTimezone($strTimezoneIdentifier) {
445			try {
446				$dtzNewTimezone = new DateTimeZone($strTimezoneIdentifier);
447				$this->SetTimezone($dtzNewTimezone);
448			} catch (Exception $objExc) {}
449		}
450
451		public function IsEqualTo(QDateTime $dttCompare) {
452			// All comparison operations MUST have operands with matching Date Nullstates
453			if ($this->blnDateNull != $dttCompare->blnDateNull)
454				return false;
455
456			// If mismatched Time nullstates, then only compare the Date portions
457			if ($this->blnTimeNull != $dttCompare->blnTimeNull) {
458				// Let's "Null Out" the Time
459				$dttThis = new QDateTime($this);
460				$dttThat = new QDateTime($dttCompare);
461				$dttThis->Hour = null;
462				$dttThat->Hour = null;
463
464				// Return the Result
465				return ($dttThis->Timestamp == $dttThat->Timestamp);
466			} else {
467				// Return the Result for the both Date and Time components
468				return ($this->Timestamp == $dttCompare->Timestamp);
469			}
470		}
471
472		public function IsEarlierThan(QDateTime $dttCompare) {
473			// All comparison operations MUST have operands with matching Date Nullstates
474			if ($this->blnDateNull != $dttCompare->blnDateNull)
475				return false;
476
477			// If mismatched Time nullstates, then only compare the Date portions
478			if ($this->blnTimeNull != $dttCompare->blnTimeNull) {
479				// Let's "Null Out" the Time
480				$dttThis = new QDateTime($this);
481				$dttThat = new QDateTime($dttCompare);
482				$dttThis->Hour = null;
483				$dttThat->Hour = null;
484
485				// Return the Result
486				return ($dttThis->Timestamp < $dttThat->Timestamp);
487			} else {
488				// Return the Result for the both Date and Time components
489				return ($this->Timestamp < $dttCompare->Timestamp);
490			}
491		}
492
493		public function IsEarlierOrEqualTo(QDateTime $dttCompare) {
494			// All comparison operations MUST have operands with matching Date Nullstates
495			if ($this->blnDateNull != $dttCompare->blnDateNull)
496				return false;
497
498			// If mismatched Time nullstates, then only compare the Date portions
499			if ($this->blnTimeNull != $dttCompare->blnTimeNull) {
500				// Let's "Null Out" the Time
501				$dttThis = new QDateTime($this);
502				$dttThat = new QDateTime($dttCompare);
503				$dttThis->Hour = null;
504				$dttThat->Hour = null;
505
506				// Return the Result
507				return ($dttThis->Timestamp <= $dttThat->Timestamp);
508			} else {
509				// Return the Result for the both Date and Time components
510				return ($this->Timestamp <= $dttCompare->Timestamp);
511			}
512		}
513
514		public function IsLaterThan(QDateTime $dttCompare) {
515			// All comparison operations MUST have operands with matching Date Nullstates
516			if ($this->blnDateNull != $dttCompare->blnDateNull)
517				return false;
518
519			// If mismatched Time nullstates, then only compare the Date portions
520			if ($this->blnTimeNull != $dttCompare->blnTimeNull) {
521				// Let's "Null Out" the Time
522				$dttThis = new QDateTime($this);
523				$dttThat = new QDateTime($dttCompare);
524				$dttThis->Hour = null;
525				$dttThat->Hour = null;
526
527				// Return the Result
528				return ($dttThis->Timestamp > $dttThat->Timestamp);
529			} else {
530				// Return the Result for the both Date and Time components
531				return ($this->Timestamp > $dttCompare->Timestamp);
532			}
533		}
534
535		public function IsLaterOrEqualTo(QDateTime $dttCompare) {
536			// All comparison operations MUST have operands with matching Date Nullstates
537			if ($this->blnDateNull != $dttCompare->blnDateNull)
538				return false;
539
540			// If mismatched Time nullstates, then only compare the Date portions
541			if ($this->blnTimeNull != $dttCompare->blnTimeNull) {
542				// Let's "Null Out" the Time
543				$dttThis = new QDateTime($this);
544				$dttThat = new QDateTime($dttCompare);
545				$dttThis->Hour = null;
546				$dttThat->Hour = null;
547
548				// Return the Result
549				return ($dttThis->Timestamp >= $dttThat->Timestamp);
550			} else {
551				// Return the Result for the both Date and Time components
552				return ($this->Timestamp >= $dttCompare->Timestamp);
553			}
554		}
555
556		public function Difference(QDateTime $dttDateTime) {
557			$intDifference = $this->Timestamp - $dttDateTime->Timestamp;
558			return new QDateTimeSpan($intDifference);
559		}
560
561		public function Add($dtsSpan){
562			if ($dtsSpan instanceof QDateTimeSpan) {
563				// And add the Span Second count to it
564				$this->Timestamp = $this->Timestamp + $dtsSpan->Seconds;
565				return $this;
566			} else if ($dtsSpan instanceof DateInterval) {
567				return parent::add($dtsSpan);
568			}
569		}
570
571		public function AddSeconds($intSeconds){
572			$this->Second += $intSeconds;
573			return $this;
574		}
575
576		public function AddMinutes($intMinutes){
577			$this->Minute += $intMinutes;
578			return $this;
579		}
580
581		public function AddHours($intHours){
582			$this->Hour += $intHours;
583			return $this;
584		}
585
586		public function AddDays($intDays){
587			$this->Day += $intDays;
588			return $this;
589		}
590
591		public function AddMonths($intMonths){
592			$this->Month += $intMonths;
593			return $this;
594		}
595
596		public function AddYears($intYears){
597			$this->Year += $intYears;
598			return $this;
599		}
600		
601		public function Modify($mixValue) {
602			parent::modify($mixValue);
603			return $this;
604		}
605
606		public function __get($strName) {
607			$this->ReinforceNullProperties();
608
609			switch ($strName) {
610				case 'Month':
611					if ($this->blnDateNull)
612						return null;
613					else
614						return (int) parent::format('m');
615
616				case 'Day':
617					if ($this->blnDateNull)
618						return null;
619					else
620						return (int) parent::format('d');
621
622				case 'Year':
623					if ($this->blnDateNull)
624						return null;
625					else
626						return (int) parent::format('Y');
627
628				case 'Hour':
629					if ($this->blnTimeNull)
630						return null;
631					else
632						return (int) parent::format('H');
633
634				case 'Minute':
635					if ($this->blnTimeNull)
636						return null;
637					else
638						return (int) parent::format('i');
639
640				case 'Second':
641					if ($this->blnTimeNull)
642						return null;
643					else
644						return (int) parent::format('s');
645
646				case 'Timestamp':
647					// Until PHP fixes a bug where lowest int is int(-2147483648) but lowest float/double is (-2147529600)
648					// We return as a "double"
649					return (double) parent::format('U');
650
651				case 'Age':
652					// Figure out the Difference from "Now"
653					$dtsFromCurrent = $this->Difference(QDateTime::Now());
654					
655					// It's in the future ('about 2 hours from now')
656					if ($dtsFromCurrent->IsPositive())
657						return $dtsFromCurrent->SimpleDisplay() . ' from now';
658
659					// It's in the past ('about 5 hours ago')
660					else if ($dtsFromCurrent->IsNegative()) {
661						$dtsFromCurrent->Seconds = abs($dtsFromCurrent->Seconds);
662						return $dtsFromCurrent->SimpleDisplay() . ' ago';
663
664					// It's current
665					} else
666						return 'right now';
667
668				default:
669					throw new QUndefinedPropertyException('GET', 'QDateTime', $strName);
670			}
671		}
672
673		public function __set($strName, $mixValue) {
674			try {
675				switch ($strName) {
676					case 'Month':
677						if ($this->blnDateNull && (!is_null($mixValue)))
678							throw new QDateTimeNullException('Cannot set the Month property on a null date.  Use SetDate().');
679						if (is_null($mixValue)) {
680							$this->blnDateNull = true;
681							$this->ReinforceNullProperties();
682							return null;
683						}
684						$mixValue = QType::Cast($mixValue, QType::Integer);
685						parent::setDate(parent::format('Y'), $mixValue, parent::format('d'));
686						return $mixValue;
687
688					case 'Day':
689						if ($this->blnDateNull && (!is_null($mixValue)))
690							throw new QDateTimeNullException('Cannot set the Day property on a null date.  Use SetDate().');
691						if (is_null($mixValue)) {
692							$this->blnDateNull = true;
693							$this->ReinforceNullProperties();
694							return null;
695						}
696						$mixValue = QType::Cast($mixValue, QType::Integer);
697						parent::setDate(parent::format('Y'), parent::format('m'), $mixValue);
698						return $mixValue;
699
700					case 'Year':
701						if ($this->blnDateNull && (!is_null($mixValue)))
702							throw new QDateTimeNullException('Cannot set the Year property on a null date.  Use SetDate().');
703						if (is_null($mixValue)) {
704							$this->blnDateNull = true;
705							$this->ReinforceNullProperties();
706							return null;
707						}
708						$mixValue = QType::Cast($mixValue, QType::Integer);
709						parent::setDate($mixValue, parent::format('m'), parent::format('d'));
710						return $mixValue;
711
712					case 'Hour':
713						if ($this->blnTimeNull && (!is_null($mixValue)))
714							throw new QDateTimeNullException('Cannot set the Hour property on a null time.  Use SetTime().');
715						if (is_null($mixValue)) {
716							$this->blnTimeNull = true;
717							$this->ReinforceNullProperties();
718							return null;
719						}
720						$mixValue = QType::Cast($mixValue, QType::Integer);
721						parent::setTime($mixValue, parent::format('i'), parent::format('s'));
722						return $mixValue;
723
724					case 'Minute':
725						if ($this->blnTimeNull && (!is_null($mixValue)))
726							throw new QDateTimeNullException('Cannot set the Minute property on a null time.  Use SetTime().');
727						if (is_null($mixValue)) {
728							$this->blnTimeNull = true;
729							$this->ReinforceNullProperties();
730							return null;
731						}
732						$mixValue = QType::Cast($mixValue, QType::Integer);
733						parent::setTime(parent::format('H'), $mixValue, parent::format('s'));
734						return $mixValue;
735
736					case 'Second':
737						if ($this->blnTimeNull && (!is_null($mixValue)))
738							throw new QDateTimeNullException('Cannot set the Second property on a null time.  Use SetTime().');
739						if (is_null($mixValue)) {
740							$this->blnTimeNull = true;
741							$this->ReinforceNullProperties();
742							return null;
743						}
744						$mixValue = QType::Cast($mixValue, QType::Integer);
745						parent::setTime(parent::format('H'), parent::format('i'), $mixValue);
746						return $mixValue;
747
748					case 'Timestamp':
749						$mixValue = QType::Cast($mixValue, QType::Integer);
750						$this->blnDateNull = false;
751						$this->blnTimeNull = false;
752
753						$this->SetDate(date('Y', $mixValue), date('m', $mixValue), date('d', $mixValue));
754						$this->SetTime(date('H', $mixValue), date('i', $mixValue), date('s', $mixValue));
755						return $mixValue;
756
757					default:
758						throw new QUndefinedPropertyException('SET', 'QDateTime', $strName);
759				}
760			} catch (QInvalidCastException $objExc) {
761				$objExc->IncrementOffset();
762				throw $objExc;
763			}
764		}
765	}
766
767/*
768	This is a reference to the documentation for hte PHP DateTime classes (as of PHP 5.2)
769
770      DateTime::ATOM
771      DateTime::COOKIE
772      DateTime::ISO8601
773      DateTime::RFC822
774      DateTime::RFC850
775      DateTime::RFC1036
776      DateTime::RFC1123
777      DateTime::RFC2822
778      DateTime::RFC3339
779      DateTime::RSS
780      DateTime::W3C
781
782      DateTime::__construct([string time[, DateTimeZone object]])
783      - Returns new DateTime object
784      
785      string DateTime::format(string format)
786      - Returns date formatted according to given format
787      
788      long DateTime::getOffset()
789      - Returns the DST offset
790      
791      DateTimeZone DateTime::getTimezone()
792      - Return new DateTimeZone object relative to give DateTime
793      
794      void DateTime::modify(string modify)
795      - Alters the timestamp
796      
797      array DateTime::parse(string date)
798      - Returns associative array with detailed info about given date
799      
800      void DateTime::setDate(long year, long month, long day)
801      - Sets the date
802      
803      void DateTime::setISODate(long year, long week[, long day])
804      - Sets the ISO date
805      
806      void DateTime::setTime(long hour, long minute[, long second])
807      - Sets the time
808      
809      void DateTime::setTimezone(DateTimeZone object)
810      - Sets the timezone for the DateTime object
811*/
812?>