/html/PEAR/Date.php
PHP | 5863 lines | 4655 code | 145 blank | 1063 comment | 132 complexity | abdae536eec33a194346063607246c06 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
-
- // {{{ Header
-
- /**
- * Generic date handling class for PEAR
- *
- * Handles time zones and changes from local standard to local Summer
- * time (daylight-saving time) through the Date_TimeZone class.
- * Supports several operations from Date_Calc on Date objects.
- *
- * PHP versions 4 and 5
- *
- * LICENSE:
- *
- * Copyright (c) 1997-2007 Baba Buehler, Pierre-Alain Joye, Firman
- * Wandayandi, C.A. Woodcock
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted under the terms of the BSD License.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Date and Time
- * @package Date
- * @author Baba Buehler <baba@babaz.com>
- * @author Pierre-Alain Joye <pajoye@php.net>
- * @author Firman Wandayandi <firman@php.net>
- * @author C.A. Woodcock <c01234@netcomuk.co.uk>
- * @copyright 1997-2007 Baba Buehler, Pierre-Alain Joye, Firman Wandayandi, C.A. Woodcock
- * @license http://www.opensource.org/licenses/bsd-license.php
- * BSD License
- * @version CVS: $Id: Date.php,v 1.89 2008/03/23 18:34:16 c01234 Exp $
- * @link http://pear.php.net/package/Date
- */
-
-
- // }}}
- // {{{ Error constants
-
- define('DATE_ERROR_INVALIDDATE', 1);
- define('DATE_ERROR_INVALIDTIME', 2);
- define('DATE_ERROR_INVALIDTIMEZONE', 3);
- define('DATE_ERROR_INVALIDDATEFORMAT', 4);
- define('DATE_ERROR_INVALIDFORMATSTRING', 5);
-
-
- // }}}
- // {{{ Includes
-
- require_once 'PEAR.php';
-
- /**
- * Load Date_TimeZone
- */
- require_once 'Date/TimeZone.php';
-
- /**
- * Load Date_Calc
- */
- require_once 'Date/Calc.php';
-
- /**
- * Load Date_Span
- */
- require_once 'Date/Span.php';
-
-
- // }}}
- // {{{ General constants
-
- /**
- * Whether to capture the micro-time (in microseconds) by default
- * in calls to 'Date::setNow()'. Note that this makes a call to
- * 'gettimeofday()', which may not work on all systems.
- *
- * @since Constant available since Release 1.5.0
- */
- define('DATE_CAPTURE_MICROTIME_BY_DEFAULT', false);
-
- /**
- * Whether to correct, by adding the local Summer time offset, the
- * specified time if it falls in the 'skipped hour' (encountered
- * when the clocks go forward).
- *
- * N.B. if specified as 'false', and if a time zone that adjusts
- * for Summer time is specified, then an object of this class will
- * be set to a semi-invalid state if an invalid time is set. That
- * is, an error will not be returned, unless the user then calls
- * a function, directly or indirectly, that accesses the time
- * part of the object. So, for example, if the user calls:
- *
- * <code>$date_object->format2('HH.MI.SS')</code> or:
- * <code>$date->object->addSeconds(30)</code>,
- *
- * an error will be returned if the time is invalid. However,
- * if the user calls:
- *
- * <code>$date->object->addDays(1)</code>,
- *
- * for example, such that the time is no longer invalid, then the
- * object will no longer be in this invalid state. This behaviour
- * is intended to minimize unexpected errors when a user uses the
- * class to do addition with days only, and does not intend to
- * access the time.
- *
- * Of course, this constant will be unused if the user chooses to
- * work in UTC or a time zone without Summer time, in which case
- * this situation will never arise.
- *
- * This constant is set to 'true' by default for backwards-compatibility
- * reasons, however, you are recommended to set it to 'false'. Note that the
- * behaviour is not intended to match that of previous versions of the class
- * in terms of ignoring the Summer time offset when making calculations which
- * involve dates in both standard and Summer time - this was recognized as a
- * bug - but in terms of returning a PEAR error object when the user sets the
- * object to an invalid date (i.e. a time in the hour which is skipped when
- * the clocks go forwards, which in Europe would be a time such as 01.30).
- * Backwards compatibility here means that the behaviour is the same as it
- * used to be, less the bug.
- *
- * Note that this problem is not an issue for the user if:
- *
- * (a) the user uses a time zone that does not observe Summer time, e.g. UTC
- * (b) the user never accesses the time, that is, he never makes a call to
- * Date::getHour() or Date::format("%H"), for example, even if he sets
- * the time to something invalid
- * (c) the user sets DATE_CORRECTINVALIDTIME_DEFAULT to true
- *
- * @since Constant available since Release 1.5.0
- */
- define('DATE_CORRECTINVALIDTIME_DEFAULT', true);
-
- /**
- * Whether to validate dates (i.e. day-month-year, ignoring the time) by
- * disallowing invalid dates (e.g. 31st February) being set by the following
- * functions:
- *
- * Date::setYear()
- * Date::setMonth()
- * Date::setDay()
- *
- * If the constant is set to 'true', then the date will be checked (by
- * default), and if invalid, an error will be returned with the Date object
- * left unmodified.
- *
- * This constant is set to 'false' by default for backwards-compatibility
- * reasons, however, you are recommended to set it to 'true'.
- *
- * Note that setHour(), setMinute(), setSecond() and setPartSecond()
- * allow an invalid date/time to be set regardless of the value of this
- * constant.
- *
- * @since Constant available since Release 1.5.0
- */
- define('DATE_VALIDATE_DATE_BY_DEFAULT', false);
-
- /**
- * Whether, by default, to accept times including leap seconds (i.e. '23.59.60')
- * when setting the date/time, and whether to count leap seconds in the
- * following functions:
- *
- * Date::addSeconds()
- * Date::subtractSeconds()
- * Date_Calc::addSeconds()
- * Date::round()
- * Date::roundSeconds()
- *
- * This constant is set to 'false' by default for backwards-compatibility
- * reasons, however, you are recommended to set it to 'true'.
- *
- * Note that this constant does not affect Date::addSpan() and
- * Date::subtractSpan() which will not count leap seconds in any case.
- *
- * @since Constant available since Release 1.5.0
- */
- define('DATE_COUNT_LEAP_SECONDS', false);
-
-
- // }}}
- // {{{ Output format constants (used in 'Date::getDate()')
-
- /**
- * "YYYY-MM-DD HH:MM:SS"
- */
- define('DATE_FORMAT_ISO', 1);
-
- /**
- * "YYYYMMSSTHHMMSS(Z|(+/-)HHMM)?"
- */
- define('DATE_FORMAT_ISO_BASIC', 2);
-
- /**
- * "YYYY-MM-SSTHH:MM:SS(Z|(+/-)HH:MM)?"
- */
- define('DATE_FORMAT_ISO_EXTENDED', 3);
-
- /**
- * "YYYY-MM-SSTHH:MM:SS(.S*)?(Z|(+/-)HH:MM)?"
- */
- define('DATE_FORMAT_ISO_EXTENDED_MICROTIME', 6);
-
- /**
- * "YYYYMMDDHHMMSS"
- */
- define('DATE_FORMAT_TIMESTAMP', 4);
-
- /**
- * long int, seconds since the unix epoch
- */
- define('DATE_FORMAT_UNIXTIME', 5);
-
-
- // }}}
- // {{{ Class: Date
-
- /**
- * Generic date handling class for PEAR
- *
- * Supports time zones with the Date_TimeZone class. Supports several
- * operations from Date_Calc on Date objects.
- *
- * Note to developers: the class stores the local time and date in the
- * local standard time. That is, it does not store the time as the
- * local Summer time when and if the time zone is in Summer time. It
- * is much easier to store local standard time and remember to offset
- * it when the user requests it.
- *
- * @category Date and Time
- * @package Date
- * @author Baba Buehler <baba@babaz.com>
- * @author Pierre-Alain Joye <pajoye@php.net>
- * @author Firman Wandayandi <firman@php.net>
- * @author C.A. Woodcock <c01234@netcomuk.co.uk>
- * @copyright 1997-2007 Baba Buehler, Pierre-Alain Joye, Firman Wandayandi, C.A. Woodcock
- * @license http://www.opensource.org/licenses/bsd-license.php
- * BSD License
- * @version Release: 1.5.0a1
- * @link http://pear.php.net/package/Date
- */
- class Date
- {
-
- // {{{ Properties
-
- /**
- * The year
- *
- * @var int
- * @access private
- * @since Property available since Release 1.0
- */
- var $year;
-
- /**
- * The month
- *
- * @var int
- * @access private
- * @since Property available since Release 1.0
- */
- var $month;
-
- /**
- * The day
- *
- * @var int
- * @access private
- * @since Property available since Release 1.0
- */
- var $day;
-
- /**
- * The hour
- *
- * @var int
- * @access private
- * @since Property available since Release 1.0
- */
- var $hour;
-
- /**
- * The minute
- *
- * @var int
- * @access private
- * @since Property available since Release 1.0
- */
- var $minute;
-
- /**
- * The second
- *
- * @var int
- * @access private
- * @since Property available since Release 1.0
- */
- var $second;
-
- /**
- * The parts of a second
- *
- * @var float
- * @access private
- * @since Property available since Release 1.4.3
- */
- var $partsecond;
-
- /**
- * The year in local standard time
- *
- * @var int
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $on_standardyear;
-
- /**
- * The month in local standard time
- *
- * @var int
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $on_standardmonth;
-
- /**
- * The day in local standard time
- *
- * @var int
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $on_standardday;
-
- /**
- * The hour in local standard time
- *
- * @var int
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $on_standardhour;
-
- /**
- * The minute in local standard time
- *
- * @var int
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $on_standardminute;
-
- /**
- * The second in local standard time
- *
- * @var int
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $on_standardsecond;
-
- /**
- * The part-second in local standard time
- *
- * @var float
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $on_standardpartsecond;
-
- /**
- * Whether the object should accept and count leap seconds
- *
- * @var bool
- * @access private
- * @since Property available since Release 1.5.0
- */
- var $ob_countleapseconds;
-
- /**
- * Whether the time is valid as a local time (an invalid time
- * is one that lies in the 'skipped hour' at the point that
- * the clocks go forward)
- *
- * @var bool
- * @access private
- * @see Date::isTimeValid()
- * @since Property available since Release 1.5.0
- */
- var $ob_invalidtime = null;
-
- /**
- * Date_TimeZone object for this date
- *
- * @var object Date_TimeZone object
- * @access private
- * @since Property available since Release 1.0
- */
- var $tz;
-
- /**
- * Defines the default weekday abbreviation length
- *
- * Formerly used by Date::format(), but now redundant - the abbreviation
- * for the current locale of the machine is used.
- *
- * @var int
- * @access private
- * @since Property available since Release 1.4.4
- */
- var $getWeekdayAbbrnameLength = 3;
-
-
- // }}}
- // {{{ Constructor
-
- /**
- * Constructor
- *
- * Creates a new Date Object initialized to the current date/time in the
- * system-default timezone by default. A date optionally
- * passed in may be in the ISO 8601, TIMESTAMP or UNIXTIME format,
- * or another Date object. If no date is passed, the current date/time
- * is used.
- *
- * If a date is passed and an exception is returned by 'setDate()'
- * there is nothing that this function can do, so for this reason, it
- * is advisable to pass no parameter and to make a separate call to
- * 'setDate()'. A date/time should only be passed if known to be a
- * valid ISO 8601 string or a valid Unix timestamp.
- *
- * @param mixed $date optional ISO 8601 date/time to initialize;
- * or, a Unix time stamp
- * @param bool $pb_countleapseconds whether to count leap seconds
- * (defaults to DATE_COUNT_LEAP_SECONDS)
- *
- * @return void
- * @access public
- * @see Date::setDate()
- */
- function Date($date = null,
- $pb_countleapseconds = DATE_COUNT_LEAP_SECONDS)
- {
- $this->ob_countleapseconds = $pb_countleapseconds;
-
- if (is_a($date, 'Date')) {
- $this->copy($date);
- } else {
- if (!is_null($date)) {
- // 'setDate()' expects a time zone to be already set:
- //
- $this->_setTZToDefault();
- $this->setDate($date);
- } else {
- $this->setNow();
- }
- }
- }
-
-
- // }}}
- // {{{ copy()
-
- /**
- * Copy values from another Date object
- *
- * Makes this Date a copy of another Date object. This is a
- * PHP4-compatible implementation of '__clone()' in PHP5.
- *
- * @param object $date Date object to copy
- *
- * @return void
- * @access public
- */
- function copy($date)
- {
- $this->year = $date->year;
- $this->month = $date->month;
- $this->day = $date->day;
- $this->hour = $date->hour;
- $this->minute = $date->minute;
- $this->second = $date->second;
- $this->partsecond = $date->partsecond;
-
- $this->on_standardyear = $date->on_standardyear;
- $this->on_standardmonth = $date->on_standardmonth;
- $this->on_standardday = $date->on_standardday;
- $this->on_standardhour = $date->on_standardhour;
- $this->on_standardminute = $date->on_standardminute;
- $this->on_standardsecond = $date->on_standardsecond;
- $this->on_standardpartsecond = $date->on_standardpartsecond;
-
- $this->ob_countleapseconds = $date->ob_countleapseconds;
- $this->ob_invalidtime = $date->ob_invalidtime;
-
- $this->tz = new Date_TimeZone($date->getTZID());
-
- $this->getWeekdayAbbrnameLength = $date->getWeekdayAbbrnameLength;
- }
-
-
- // }}}
- // {{{ __clone()
-
- /**
- * Copy values from another Date object
- *
- * Makes this Date a copy of another Date object. For PHP5
- * only.
- *
- * @return void
- * @access public
- * @see Date::copy()
- */
- function __clone()
- {
- // This line of code would be preferable, but will only
- // compile in PHP5:
- //
- // $this->tz = clone $this->tz;
-
- $this->tz = new Date_TimeZone($this->getTZID());
- }
-
-
- // }}}
- // {{{ setDate()
-
- /**
- * Sets the fields of a Date object based on the input date and format
- *
- * Format parameter should be one of the specified DATE_FORMAT_* constants:
- *
- * <code>DATE_FORMAT_ISO</code>
- * - 'YYYY-MM-DD HH:MI:SS'
- * <code>DATE_FORMAT_ISO_BASIC</code>
- * - 'YYYYMMSSTHHMMSS(Z|(+/-)HHMM)?'
- * <code>DATE_FORMAT_ISO_EXTENDED</code>
- * - 'YYYY-MM-SSTHH:MM:SS(Z|(+/-)HH:MM)?'
- * <code>DATE_FORMAT_ISO_EXTENDED_MICROTIME</code>
- * - 'YYYY-MM-SSTHH:MM:SS(.S*)?(Z|(+/-)HH:MM)?'
- * <code>DATE_FORMAT_TIMESTAMP</code>
- * - 'YYYYMMDDHHMMSS'
- * <code>DATE_FORMAT_UNIXTIME'</code>
- * - long integer of the no of seconds since
- * the Unix Epoch
- * (1st January 1970 00.00.00 GMT)
- *
- * @param string $date input date
- * @param int $format optional format constant
- * (DATE_FORMAT_*) of the input date.
- * This parameter is not needed,
- * except to force the setting of the
- * date from a Unix time-stamp
- * (DATE_FORMAT_UNIXTIME).
- * @param bool $pb_repeatedhourdefault value to return if repeated
- * hour is specified (defaults
- * to false)
- *
- * @return void
- * @access public
- */
- function setDate($date,
- $format = DATE_FORMAT_ISO,
- $pb_repeatedhourdefault = false)
- {
-
- if (preg_match('/^([0-9]{4,4})-?(0[1-9]|1[0-2])-?(0[1-9]|[12][0-9]|3[01])' .
- '([T\s]?([01][0-9]|2[0-3]):?' . // [hh]
- '([0-5][0-9]):?([0-5][0-9]|60)(\.\d+)?' . // [mi]:[ss]
- '(Z|[+\-][0-9]{2,2}(:?[0-5][0-9])?)?)?$/i', // offset
- $date, $regs) &&
- $format != DATE_FORMAT_UNIXTIME
- ) {
- // DATE_FORMAT_ISO, ISO_BASIC, ISO_EXTENDED, and TIMESTAMP
- // These formats are extremely close to each other. This regex
- // is very loose and accepts almost any butchered format you could
- // throw at it. e.g. 2003-10-07 19:45:15 and 2003-10071945:15
- // are the same thing in the eyes of this regex, even though the
- // latter is not a valid ISO 8601 date.
-
- if (!Date_Calc::isValidDate($regs[3], $regs[2], $regs[1])) {
- return PEAR::raiseError("'" .
- Date_Calc::dateFormat($regs[1],
- $regs[2],
- $regs[3],
- "%Y-%m-%d") .
- "' is invalid calendar date",
- DATE_ERROR_INVALIDDATE);
- }
-
- if (isset($regs[9])) {
- if ($regs[9] == "Z") {
- $this->tz = new Date_TimeZone("UTC");
- } else {
- $this->tz = new Date_TimeZone("UTC" . $regs[9]);
- }
- }
-
- $this->setLocalTime($regs[3],
- $regs[2],
- $regs[1],
- isset($regs[5]) ? $regs[5] : 0,
- isset($regs[6]) ? $regs[6] : 0,
- isset($regs[7]) ? $regs[7] : 0,
- isset($regs[8]) ? $regs[8] : 0.0,
- $pb_repeatedhourdefault);
-
- } else if (is_numeric($date)) {
- // Unix Time; N.B. Unix Time is defined relative to GMT,
- // so it needs to be adjusted for the current time zone;
- // however we do not know if it is in Summer time until
- // we have converted it from Unix time:
- //
-
- // Get current time zone details:
- //
- $hs_id = $this->getTZID();
-
- // Input Unix time as UTC:
- //
- $this->tz = new Date_TimeZone("UTC");
- $this->setDate(gmdate("Y-m-d H:i:s", $date));
-
- // Convert back to correct time zone:
- //
- $this->convertTZByID($hs_id);
- } else {
- return PEAR::raiseError("Date not in ISO 8601 format",
- DATE_ERROR_INVALIDDATEFORMAT);
- }
- }
-
-
- // }}}
- // {{{ setNow()
-
- /**
- * Sets to local current time and time zone
- *
- * @param bool $pb_setmicrotime whether to set micro-time (defaults to the
- * value of the constant
- * DATE_CAPTURE_MICROTIME_BY_DEFAULT)
- *
- * @return void
- * @access public
- * @since Method available since Release 1.5.0
- */
- function setNow($pb_setmicrotime = DATE_CAPTURE_MICROTIME_BY_DEFAULT)
- {
- $this->_setTZToDefault();
-
- if ($pb_setmicrotime) {
- $ha_unixtime = gettimeofday();
- } else {
- $ha_unixtime = array("sec" => time());
- }
-
- $this->setDate(date("Y-m-d H:i:s", $ha_unixtime["sec"]) .
- (isset($ha_unixtime["usec"]) ?
- "." . sprintf("%06d", $ha_unixtime["usec"]) :
- ""));
- }
-
-
- // }}}
- // {{{ round()
-
- /**
- * Rounds the date according to the specified precision (defaults
- * to nearest day)
- *
- * The precision parameter must be one of the following constants:
- *
- * <code>DATE_PRECISION_YEAR</code>
- * <code>DATE_PRECISION_MONTH</code>
- * <code>DATE_PRECISION_DAY</code>
- * <code>DATE_PRECISION_HOUR</code>
- * <code>DATE_PRECISION_10MINUTES</code>
- * <code>DATE_PRECISION_MINUTE</code>
- * <code>DATE_PRECISION_10SECONDS</code>
- * <code>DATE_PRECISION_SECOND</code>
- *
- * N.B. the default is DATE_PRECISION_DAY
- *
- * The precision can also be specified as an integral offset from
- * one of these constants, where the offset reflects a precision
- * of 10 to the power of the offset greater than the constant.
- * For example:
- *
- * <code>DATE_PRECISION_YEAR - 1</code> rounds the date to the nearest 10
- * years
- * <code>DATE_PRECISION_YEAR - 3</code> rounds the date to the nearest 1000
- * years
- * <code>DATE_PRECISION_SECOND + 1</code> rounds the date to 1 decimal
- * point of a second
- * <code>DATE_PRECISION_SECOND + 3</code> rounds the date to 3 decimal
- * points of a second
- * <code>DATE_PRECISION_SECOND - 1</code> rounds the date to the nearest 10
- * seconds (thus it is equivalent to
- * DATE_PRECISION_10SECONDS)
- *
- * @param int $pn_precision a 'DATE_PRECISION_*' constant
- * @param bool $pb_correctinvalidtime whether to correct, by adding the
- * local Summer time offset, the rounded
- * time if it falls in the skipped hour
- * (defaults to
- * DATE_CORRECTINVALIDTIME_DEFAULT)
- *
- * @return void
- * @access public
- * @since Method available since Release 1.5.0
- */
- function round($pn_precision = DATE_PRECISION_DAY,
- $pb_correctinvalidtime = DATE_CORRECTINVALIDTIME_DEFAULT)
- {
- if ($pn_precision <= DATE_PRECISION_DAY) {
- list($hn_year,
- $hn_month,
- $hn_day,
- $hn_hour,
- $hn_minute,
- $hn_secondraw) =
- Date_Calc::round($pn_precision,
- $this->day,
- $this->month,
- $this->year,
- $this->hour,
- $this->minute,
- $this->partsecond == 0.0 ?
- $this->second :
- $this->second + $this->partsecond,
- $this->ob_countleapseconds);
- if (is_float($hn_secondraw)) {
- $hn_second = intval($hn_secondraw);
- $hn_partsecond = $hn_secondraw - $hn_second;
- } else {
- $hn_second = $hn_secondraw;
- $hn_partsecond = 0.0;
- }
-
- $this->setLocalTime($hn_day,
- $hn_month,
- $hn_year,
- $hn_hour,
- $hn_minute,
- $hn_second,
- $hn_partsecond,
- true, // This is unlikely anyway, but the
- // day starts with the repeated hour
- // the first time around
- $pb_correctinvalidtime);
- return;
- }
-
- // ($pn_precision >= DATE_PRECISION_HOUR)
- //
- if ($this->tz->getDSTSavings() % 3600000 == 0 ||
- ($this->tz->getDSTSavings() % 60000 == 0 &&
- $pn_precision >= DATE_PRECISION_MINUTE)
- ) {
- list($hn_year,
- $hn_month,
- $hn_day,
- $hn_hour,
- $hn_minute,
- $hn_secondraw) =
- Date_Calc::round($pn_precision,
- $this->on_standardday,
- $this->on_standardmonth,
- $this->on_standardyear,
- $this->on_standardhour,
- $this->on_standardminute,
- $this->on_standardpartsecond == 0.0 ?
- $this->on_standardsecond :
- $this->on_standardsecond +
- $this->on_standardpartsecond,
- $this->ob_countleapseconds);
- if (is_float($hn_secondraw)) {
- $hn_second = intval($hn_secondraw);
- $hn_partsecond = $hn_secondraw - $hn_second;
- } else {
- $hn_second = $hn_secondraw;
- $hn_partsecond = 0.0;
- }
-
- $this->setStandardTime($hn_day,
- $hn_month,
- $hn_year,
- $hn_hour,
- $hn_minute,
- $hn_second,
- $hn_partsecond);
- return;
- }
-
- // Very unlikely anyway (as I write, the only time zone like this
- // is Lord Howe Island in Australia (offset of half an hour)):
- //
- // (This algorithm could be better)
- //
- list($hn_year,
- $hn_month,
- $hn_day,
- $hn_hour,
- $hn_minute,
- $hn_secondraw) =
- Date_Calc::round($pn_precision,
- $this->day,
- $this->month,
- $this->year,
- $this->hour,
- $this->minute,
- $this->partsecond == 0.0 ?
- $this->second :
- $this->second + $this->partsecond,
- $this->ob_countleapseconds);
- if (is_float($hn_secondraw)) {
- $hn_second = intval($hn_secondraw);
- $hn_partsecond = $hn_secondraw - $hn_second;
- } else {
- $hn_second = $hn_secondraw;
- $hn_partsecond = 0.0;
- }
-
- $this->setLocalTime($hn_day,
- $hn_month,
- $hn_year,
- $hn_hour,
- $hn_minute,
- $hn_second,
- $hn_partsecond,
- false, // This will be right half the time
- $pb_correctinvalidtime); // This will be right
- // some of the time
- // (depends on Summer
- // time offset)
- }
-
-
- // }}}
- // {{{ roundSeconds()
-
- /**
- * Rounds seconds up or down to the nearest specified unit
- *
- * N.B. this function is equivalent to calling:
- * <code>'round(DATE_PRECISION_SECOND + $pn_precision)'</code>
- *
- * @param int $pn_precision number of digits after the decimal point
- * @param bool $pb_correctinvalidtime whether to correct, by adding the
- * local Summer time offset, the rounded
- * time if it falls in the skipped hour
- * (defaults to
- * DATE_CORRECTINVALIDTIME_DEFAULT)
- *
- * @return void
- * @access public
- * @since Method available since Release 1.5.0
- */
- function roundSeconds($pn_precision = 0,
- $pb_correctinvalidtime = DATE_CORRECTINVALIDTIME_DEFAULT)
- {
- $this->round(DATE_PRECISION_SECOND + $pn_precision,
- $pb_correctinvalidtime);
- }
-
-
- // }}}
- // {{{ trunc()
-
- /**
- * Truncates the date according to the specified precision (by
- * default, it truncates the time part of the date)
- *
- * The precision parameter must be one of the following constants:
- *
- * <code>DATE_PRECISION_YEAR</code>
- * <code>DATE_PRECISION_MONTH</code>
- * <code>DATE_PRECISION_DAY</code>
- * <code>DATE_PRECISION_HOUR</code>
- * <code>DATE_PRECISION_10MINUTES</code>
- * <code>DATE_PRECISION_MINUTE</code>
- * <code>DATE_PRECISION_10SECONDS</code>
- * <code>DATE_PRECISION_SECOND</code>
- *
- * N.B. the default is DATE_PRECISION_DAY
- *
- * The precision can also be specified as an integral offset from
- * one of these constants, where the offset reflects a precision
- * of 10 to the power of the offset greater than the constant.
- * For example:
- *
- * <code>DATE_PRECISION_YEAR</code> truncates the month, day and time
- * part of the year
- * <code>DATE_PRECISION_YEAR - 1</code> truncates the unit part of the
- * year, e.g. 1987 becomes 1980
- * <code>DATE_PRECISION_YEAR - 3</code> truncates the hundreds part of the
- * year, e.g. 1987 becomes 1000
- * <code>DATE_PRECISION_SECOND + 1</code> truncates the part of the second
- * less than 0.1 of a second, e.g.
- * 3.26301 becomes 3.2 seconds
- * <code>DATE_PRECISION_SECOND + 3</code> truncates the part of the second
- * less than 0.001 of a second, e.g.
- * 3.26301 becomes 3.263 seconds
- * <code>DATE_PRECISION_SECOND - 1</code> truncates the unit part of the
- * seconds (thus it is equivalent to
- * DATE_PRECISION_10SECONDS)
- *
- * @param int $pn_precision a 'DATE_PRECISION_*' constant
- * @param bool $pb_correctinvalidtime whether to correct, by adding the
- * local Summer time offset, the
- * truncated time if it falls in the
- * skipped hour (defaults to
- * DATE_CORRECTINVALIDTIME_DEFAULT)
- *
- * @return void
- * @access public
- * @since Method available since Release 1.5.0
- */
- function trunc($pn_precision = DATE_PRECISION_DAY,
- $pb_correctinvalidtime = DATE_CORRECTINVALIDTIME_DEFAULT)
- {
- if ($pn_precision <= DATE_PRECISION_DAY) {
- if ($pn_precision <= DATE_PRECISION_YEAR) {
- $hn_month = 0;
- $hn_day = 0;
- $hn_hour = 0;
- $hn_minute = 0;
- $hn_second = 0;
- $hn_partsecond = 0.0;
-
- $hn_invprecision = DATE_PRECISION_YEAR - $pn_precision;
- if ($hn_invprecision > 0) {
- $hn_year = intval($this->year / pow(10, $hn_invprecision)) *
- pow(10, $hn_invprecision);
- //
- // (Conversion to int necessary for PHP <= 4.0.6)
- } else {
- $hn_year = $this->year;
- }
- } else if ($pn_precision == DATE_PRECISION_MONTH) {
- $hn_year = $this->year;
- $hn_month = $this->month;
- $hn_day = 0;
- $hn_hour = 0;
- $hn_minute = 0;
- $hn_second = 0;
- $hn_partsecond = 0.0;
- } else if ($pn_precision == DATE_PRECISION_DAY) {
- $hn_year = $this->year;
- $hn_month = $this->month;
- $hn_day = $this->day;
- $hn_hour = 0;
- $hn_minute = 0;
- $hn_second = 0;
- $hn_partsecond = 0.0;
- }
-
- $this->setLocalTime($hn_day,
- $hn_month,
- $hn_year,
- $hn_hour,
- $hn_minute,
- $hn_second,
- $hn_partsecond,
- true, // This is unlikely anyway, but the
- // day starts with the repeated
- // hour the first time around
- $pb_correctinvalidtime);
- return;
- }
-
- // Precision is at least equal to DATE_PRECISION_HOUR
- //
- if ($pn_precision == DATE_PRECISION_HOUR) {
- $this->addSeconds($this->partsecond == 0.0 ?
- -$this->second :
- -$this->second - $this->partsecond);
- //
- // (leap seconds irrelevant)
-
- $this->addMinutes(-$this->minute);
- } else if ($pn_precision <= DATE_PRECISION_MINUTE) {
- if ($pn_precision == DATE_PRECISION_10MINUTES) {
- $this->addMinutes(-$this->minute % 10);
- }
-
- $this->addSeconds($this->partsecond == 0.0 ?
- -$this->second :
- -$this->second - $this->partsecond);
- //
- // (leap seconds irrelevant)
-
- } else if ($pn_precision == DATE_PRECISION_10SECONDS) {
- $this->addSeconds($this->partsecond == 0.0 ?
- -$this->second % 10 :
- (-$this->second % 10) - $this->partsecond);
- //
- // (leap seconds irrelevant)
-
- } else {
- // Assume Summer time offset cannot be composed of part-seconds:
- //
- $hn_precision = $pn_precision - DATE_PRECISION_SECOND;
- $hn_partsecond = intval($this->on_standardpartsecond *
- pow(10, $hn_precision)) /
- pow(10, $hn_precision);
- $this->setStandardTime($this->on_standardday,
- $this->on_standardmonth,
- $this->on_standardyear,
- $this->on_standardhour,
- $this->on_standardminute,
- $this->on_standardsecond,
- $hn_partsecond);
- }
- }
-
-
- // }}}
- // {{{ truncSeconds()
-
- /**
- * Truncates seconds according to the specified precision
- *
- * N.B. this function is equivalent to calling:
- * <code>'Date::trunc(DATE_PRECISION_SECOND + $pn_precision)'</code>
- *
- * @param int $pn_precision number of digits after the decimal point
- * @param bool $pb_correctinvalidtime whether to correct, by adding the
- * local Summer time offset, the
- * truncated time if it falls in the
- * skipped hour (defaults to
- * DATE_CORRECTINVALIDTIME_DEFAULT)
- *
- * @return void
- * @access public
- * @since Method available since Release 1.5.0
- */
- function truncSeconds($pn_precision = 0,
- $pb_correctinvalidtime = DATE_CORRECTINVALIDTIME_DEFAULT)
- {
- $this->trunc(DATE_PRECISION_SECOND + $pn_precision,
- $pb_correctinvalidtime);
- }
-
-
- // }}}
- // {{{ getDate()
-
- /**
- * Gets a string (or other) representation of this date
- *
- * Returns a date in the format specified by the DATE_FORMAT_* constants.
- *
- * @param int $format format constant (DATE_FORMAT_*) of the output date
- *
- * @return string the date in the requested format
- * @access public
- */
- function getDate($format = DATE_FORMAT_ISO)
- {
- switch ($format) {
- case DATE_FORMAT_ISO:
- return $this->format("%Y-%m-%d %T");
- break;
- case DATE_FORMAT_ISO_BASIC:
- $format = "%Y%m%dT%H%M%S";
- if ($this->getTZID() == 'UTC') {
- $format .= "Z";
- }
- return $this->format($format);
- break;
- case DATE_FORMAT_ISO_EXTENDED:
- $format = "%Y-%m-%dT%H:%M:%S";
- if ($this->getTZID() == 'UTC') {
- $format .= "Z";
- }
- return $this->format($format);
- break;
- case DATE_FORMAT_ISO_EXTENDED_MICROTIME:
- $format = "%Y-%m-%dT%H:%M:%s";
- if ($this->getTZID() == 'UTC') {
- $format .= "Z";
- }
- return $this->format($format);
- break;
- case DATE_FORMAT_TIMESTAMP:
- return $this->format("%Y%m%d%H%M%S");
- break;
- case DATE_FORMAT_UNIXTIME:
- // Enter a time in UTC, so use 'gmmktime()' (the alternative
- // is to offset additionally by the local time, but the object
- // is not necessarily using local time):
- //
- if ($this->ob_invalidtime)
- return $this->_getErrorInvalidTime();
-
- return gmmktime($this->on_standardhour,
- $this->on_standardminute,
- $this->on_standardsecond,
- $this->on_standardmonth,
- $this->on_standardday,
- $this->on_standardyear) -
- $this->tz->getRawOffset() / 1000; // N.B. Unix-time excludes
- // leap seconds by
- // definition
- break;
- }
- }
-
-
- // }}}
- // {{{ format()
-
- /**
- * Date pretty printing, similar to strftime()
- *
- * Formats the date in the given format, much like
- * strftime(). Most strftime() options are supported.<br><br>
- *
- * Formatting options:<br><br>
- *
- * <code>%a </code> abbreviated weekday name (Sun, Mon, Tue) <br>
- * <code>%A </code> full weekday name (Sunday, Monday, Tuesday) <br>
- * <code>%b </code> abbreviated month name (Jan, Feb, Mar) <br>
- * <code>%B </code> full month name (January, February, March) <br>
- * <code>%C </code> century number (the year divided by 100 and truncated
- * to an integer, range 00 to 99) <br>
- * <code>%d </code> day of month (range 00 to 31) <br>
- * <code>%D </code> equivalent to "%m/%d/%y" <br>
- * <code>%e </code> day of month without leading noughts (range 0 to 31) <br>
- * <code>%E </code> Julian day - no of days since Monday, 24th November,
- * 4714 B.C. (in the proleptic Gregorian calendar) <br>
- * <code>%g </code> like %G, but without the century <br>
- * <code>%G </code> the 4-digit year corresponding to the ISO week
- * number (see %V). This has the same format and value
- * as %Y, except that if the ISO week number belongs
- * to the previous or next year, that year is used
- * instead. <br>
- * <code>%h </code> hour as decimal number without leading noughts (0
- * to 23) <br>
- * <code>%H </code> hour as decimal number (00 to 23) <br>
- * <code>%i </code> hour as decimal number on 12-hour clock without
- * leading noughts (1 to 12) <br>
- * <code>%I </code> hour as decimal number on 12-hour clock (01 to 12) <br>
- * <code>%j </code> day of year (range 001 to 366) <br>
- * <code>%m </code> month as decimal number (range 01 to 12) <br>
- * <code>%M </code> minute as a decimal number (00 to 59) <br>
- * <code>%n </code> newline character ("\n") <br>
- * <code>%o </code> raw timezone offset expressed as '+/-HH:MM' <br>
- * <code>%O </code> dst-corrected timezone offset expressed as '+/-HH:MM' <br>
- * <code>%p </code> either 'am' or 'pm' depending on the time <br>
- * <code>%P </code> either 'AM' or 'PM' depending on the time <br>
- * <code>%r </code> time in am/pm notation; equivalent to "%I:%M:%S %p" <br>
- * <code>%R </code> time in 24-hour notation; equivalent to "%H:%M" <br>
- * <code>%s </code> seconds including the micro-time (the decimal
- * representation less than one second to six decimal
- * places<br>
- * <code>%S </code> seconds as a decimal number (00 to 59) <br>
- * <code>%t </code> tab character ("\t") <br>
- * <code>%T </code> current time; equivalent to "%H:%M:%S" <br>
- * <code>%u </code> day of week as decimal (1 to 7; where 1 = Monday) <br>
- * <code>%U </code> week number of the current year as a decimal
- * number, starting with the first Sunday as the first
- * day of the first week (i.e. the first full week of
- * the year, and the week that contains 7th January)
- * (00 to 53) <br>
- * <code>%V </code> the ISO 8601:1988 week number of the current year
- * as a decimal number, range 01 to 53, where week 1
- * is the first week that has at least 4 days in the
- * current year, and with Monday as the first day of
- * the week. (Use %G or %g for the year component
- * that corresponds to the week number for the
- * specified timestamp.)
- * <code>%w </code> day of week as decimal (0 to 6; where 0 = Sunday) <br>
- * <code>%W </code> week number of the current year as a decimal
- * number, starting with the first Monday as the first
- * day of the first week (i.e. the first full week of
- * the year, and the week that contains 7th January)
- * (00 to 53) <br>
- * <code>%y </code> year as decimal (range 00 to 99) <br>
- * <code>%Y </code> year as decimal including century (range 0000 to
- * 9999) <br>
- * <code>%Z </code> Abbreviated form of time zone name, e.g. 'GMT', or
- * the abbreviation for Summer time if the date falls
- * in Summer time, e.g. 'BST'. <br>
- * <code>%% </code> literal '%' <br>
- * <br>
- *
- * The following codes render a different output to that of 'strftime()':
- *
- * <code>%e</code> in 'strftime()' a single digit is preceded by a space
- * <code>%h</code> in 'strftime()' is equivalent to '%b'
- * <code>%U</code> '%U' and '%W' are different in 'strftime()' in that
- * if week 1 does not start on 1st January, '00' is
- * returned, whereas this function returns '53', that is,
- * the week is counted as the last of the previous year.
- * <code>%W</code>
- *
- * @param string $format the format string for returned date/time
- *
- * @return string date/time in given format
- * @access public
- */
- function format($format)
- {
- $output = "";
-
- $hn_isoyear = null;
- $hn_isoweek = null;
- $hn_isoday = null;
-
- for ($strpos = 0; $strpos < strlen($format); $strpos++) {
- $char = substr($format, $strpos, 1);
- if ($char == "%") {
- $nextchar = substr($format, $strpos + 1, 1);
- switch ($nextchar) {
- case "a":
- $output .= Date_Calc::getWeekdayAbbrname($this->day,
- $this->month, $this->year,
- $this->getWeekdayAbbrnameLength);
- break;
- case "A":
- $output .= Date_Calc::getWeekdayFullname($this->day,
- $this->month, $this->year);
- break;
- case "b":
- $output .= Date_Calc::getMonthAbbrname($this->month);
- break;
- case "B":
- $output .= Date_Calc::getMonthFullname($this->month);
- break;
- case "C":
- $output .= sprintf("%02d", intval($this->year / 100));
- break;
- case "d":
- $output .= sprintf("%02d", $this->day);
- break;
- case "D":
- $output .= sprintf("%02d/%02d/%02d", $this->month,
- $this->day, $this->year);
- break;
- case "e":
- $output .= $this->day;
- break;
- case "E":
- $output .= Date_Calc::dateToDays($this->day, $this->month,
- $this->year);
- break;
- case "g":
- if (is_null($hn_isoyear))
- list($hn_isoyear, $hn_isoweek, $hn_isoday) =
- Date_Calc::isoWeekDate($this->day,
- $this->month,
- $this->year);
-
- $output .= sprintf("%02d", $hn_isoyear % 100);
- break;
- case "G":
- if (is_null($hn_isoyear))
- list($hn_isoyear, $hn_isoweek, $hn_isoday) =
- Date_Calc::isoWeekDate($this->day,
- $this->month,
- $this->year);
-
- $output .= sprintf("%04d", $hn_isoyear);
- break;
- case 'h':
- if ($this->ob_invalidtime)
- return $this->_getErrorInvalidTime();
- $output .= sprintf("%d", $this->hour);
- break;
- case "H":
- if ($this->ob_invalidtime)
- return $this->_getErrorInvalidTime();
- $output .= sprintf("%02d", $this->hour);
- break;
- case "i":
- case "I":
- if ($this->ob_invalidtime)
- …
Large files files are truncated, but you can click here to view the full file