/tine20/library/qCal/lib/qCal/DateTime.php
PHP | 258 lines | 96 code | 44 blank | 118 comment | 16 complexity | b725516959abc605f0f07632b3b17677 MD5 | raw file
- <?php
- /**
- * Date/Time Object
- *
- * In order to perform all the complex date/time based math and logic required to
- * implement the iCalendar spec, we need a complex date/time class. This class represents
- * a specific point in time, including the time. Internally it makes use of qCal_Date and
- * qCal_Time. If only a date or only a time needs to be represented, then one of those
- * classes should be used.
- *
- * @package qCal
- * @subpackage qCal_DateTime
- * @copyright Luke Visinoni (luke.visinoni@gmail.com)
- * @author Luke Visinoni (luke.visinoni@gmail.com)
- * @license GNU Lesser General Public License
- */
- class qCal_DateTime {
- /**
- * @var qCal_Date An object that represents the date
- */
- protected $date;
-
- /**
- * @var qCal_Time An object that represents the time
- */
- protected $time;
-
- /**
- * @var string The default string representation of datetime is a direct
- * correlation to the date function's "c" metacharacter
- */
- protected $format = "Y-m-d\TH:i:sP";
-
- /**
- * Class constructor
- * @param integer $year
- * @param integer $month
- * @param integer $day
- * @param integer $hour
- * @param integer $minute
- * @param integer $second
- * @param mixed $timezone Either a qCal_Timezone object or a string representing one
- * @param boolean $rollover Set to true to be able to specify things like
- * 100 seconds and have it roll over to one minute, forty seconds
- * @access public
- * @todo Make this default to "now"
- * @todo It is possible that the timezone could put the date back (or forward?) a day. This does not account for that
- */
- public function __construct($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null, $rollover = null) {
-
- $date = new qCal_Date($year, $month, $day, $rollover);
- $time = new qCal_Time($hour, $minute, $second, $timezone, $rollover);
- $this->setDate($date);
- $this->setTime($time);
-
- }
-
- /**
- * Generate a datetime object from a string (much like PHP's strtotime function)
- * @param string A date/time string to convert into a qCal_DateTime object
- * @param mixed Either a qCal_Timezone object or a string representing one
- * @return qCal_DateTime
- * @access public
- * @todo Should this accept qCal_Date and qCal_DateTime objects?
- */
- public static function factory($datetime, $timezone = null) {
- if (substr($datetime,0,4)=='TZID') {
- // Handle DateTime with Timezones
- $buffer = explode(';', $datetime, 2);
- $datetime = $buffer[1];
- $buffer = explode('=', $buffer[0], 2);
- $timezone = $buffer[1];
- }
- if (is_null($timezone) || !($timezone instanceof qCal_Timezone)) {
- // @todo Make sure this doesn't cause any issues
- // detect if we're working with a UTC string like "19970101T180000Z", where the Z means use UTC time
- if (strtolower(substr($datetime, -1)) == "z") {
- $timezone = "UTC";
- }
- $timezone = qCal_Timezone::factory($timezone);
- }
- // get the default timezone so we can set it back to it later
- $tz = date_default_timezone_get();
- // set the timezone to GMT temporarily
- date_default_timezone_set("GMT");
-
- // handles unix timestamp
- if (is_integer($datetime) || ctype_digit((string) $datetime)) {
- $timestamp = $datetime;
- } else {
- // handles just about any string representation of date/time (strtotime)
- if (is_string($datetime) || empty($datetime)) {
- if (!$timestamp = strtotime($datetime)) {
- // if unix timestamp can't be created throw an exception
- throw new qCal_DateTime_Exception("Invalid or ambiguous date/time string passed to qCal_DateTime::factory()");
- }
- }
- }
-
- if (!isset($timestamp)) {
- throw new qCal_DateTime_Exception("Could not generate a qCal_DateTime object.");
- }
-
- list($year, $month, $day, $hour, $minute, $second) = explode("|", gmdate("Y|m|d|H|i|s", $timestamp));
-
- // set the timezone back to what it was
- date_default_timezone_set($tz);
-
- return new qCal_DateTime($year, $month, $day, $hour, $minute, $second, $timezone);
-
- }
-
- /**
- * Set the date component
- * @param qCal_Date The date component portion of this object
- * @return $this
- * @access protected
- */
- protected function setDate(qCal_Date $date) {
-
- $this->date = $date;
- return $this;
-
- }
-
- /**
- * Set the time component
- * @param qCal_Time The time component portion of this object
- * @return $this
- * @access protected
- */
- protected function setTime(qCal_Time $time) {
-
- $this->time = $time;
- return $this;
-
- }
-
- /**
- * Get time portion as object
- * @return qCal_Time The time component portion of this object
- * @access public
- */
- public function getTime() {
-
- return $this->time;
-
- }
-
- /**
- * Get date portion as object
- * @return qCal_Date The date component portion of this object
- * @access public
- */
- public function getDate() {
-
- return $this->date;
-
- }
-
- /**
- * Get unix timestamp
- * @param boolean $useOffset Set to true if you want the timestamp to
- * consider the timezone's offset
- * @return integer The unix timestamp of this object
- * @access public
- */
- public function getUnixTimestamp($useOffset = true) {
-
- return $this->date->getUnixTimestamp() + $this->time->getTimestamp($useOffset);
-
- }
-
- /**
- * Set the format to use when outputting as a string
- * @param string $format The format that is to be used when this object is
- * converted to a string. Use the same metacharacters that are used in PHP's date function
- * @return $this
- * @access public
- */
- public function setFormat($format) {
-
- $this->format = (string) $format;
- return $this;
-
- }
-
- /**
- * Format the date/time using PHP's date() function's meta-characters
- * @param string $format Use the PHP date() function's meta-characters to convert this object to a string
- * @return string The formatted date/time string
- * @access public
- * @todo It's obvious I need to find a better solution to formatting since I have repeated this method
- * in three classes now...
- */
- public function format($format) {
-
- $escape = false;
- $meta = str_split($format);
- $output = array();
- foreach($meta as $char) {
- if ($char == '\\') {
- $escape = true;
- continue;
- }
- if (!$escape && $this->convertChar($char) != $char) {
- $output[] = $this->convertChar($char);
- } else {
- $output[] = $char;
- }
- // reset this to false after every iteration that wasn't "continued"
- $escape = false;
- }
- return implode($output);
-
- }
-
- /**
- * Converts a metacharacter into its date/time counter-part.
- * @param string $char The metacharacter that is to be converted
- * @return string The converted date/time value
- * @access public
- */
- protected function convertChar($char) {
-
- $char = $this->date->format($char);
- $char = $this->time->format($char);
- $char = $this->time->getTimezone()->format($char);
- return $char;
-
- }
-
- /**
- * Output date/time as string
- * @return string The string representation of this object
- * @access public
- */
- public function __toString() {
-
- return $this->format($this->format);
-
- }
-
- /**
- * Get date/time as UTC
- * @param boolean $humanReadable Set to true if you want the result to be a more human-oriented format
- * @return string The UTC-formatted date/time
- * @access public
- */
- public function getUtc($humanReadable = false) {
-
- if ($humanReadable) return gmdate('Y-m-d', $this->date->getUnixTimestamp()) . gmdate('\TH:i:s\Z', $this->time->getTimestamp());
- else return gmdate('Ymd', $this->date->getUnixTimestamp()) . gmdate('\THis\Z', $this->time->getTimestamp());
-
- }
- }