Ejemplo n.º 1
0
 /**
  * Rounds the date according to the specified precision
  *
  * 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>
  *
  * 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 + 1</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)
  *
  * N.B. This function requires a time in UTC if both the precision is at
  * least DATE_PRECISION_SECOND and leap seconds are being counted, otherwise
  * any local time is acceptable.
  *
  * @param int   $pn_precision a 'DATE_PRECISION_*' constant
  * @param int   $pn_day       the day of the month
  * @param int   $pn_month     the month
  * @param int   $pn_year      the year
  * @param int   $pn_hour      the hour
  * @param int   $pn_minute    the minute
  * @param mixed $pn_second    the second as integer or float
  * @param bool  $pb_countleap whether to count leap seconds (defaults to
  *                             DATE_COUNT_LEAP_SECONDS)
  *
  * @return   array      array of year, month, day, hour, minute, second
  * @access   public
  * @static
  * @since    Method available since Release 1.5.0
  */
 function round($pn_precision, $pn_day, $pn_month, $pn_year, $pn_hour = 0, $pn_minute = 0, $pn_second = 0, $pb_countleap = DATE_COUNT_LEAP_SECONDS)
 {
     if ($pn_precision <= DATE_PRECISION_YEAR) {
         $hn_month = 0;
         $hn_day = 0;
         $hn_hour = 0;
         $hn_minute = 0;
         $hn_second = 0;
         if ($pn_precision < DATE_PRECISION_YEAR) {
             $hn_year = round($pn_year, $pn_precision - DATE_PRECISION_YEAR);
         } else {
             // Check part-year:
             //
             $hn_midyear = (Date_Calc::firstDayOfYear($pn_year + 1) - Date_Calc::firstDayOfYear($pn_year)) / 2;
             if (($hn_days = Date_Calc::dayOfYear($pn_day, $pn_month, $pn_year)) <= $hn_midyear - 1) {
                 $hn_year = $pn_year;
             } else {
                 if ($hn_days >= $hn_midyear) {
                     // Round up:
                     //
                     $hn_year = $pn_year + 1;
                 } else {
                     // Take time into account:
                     //
                     $hn_partday = Date_Calc::secondsPastMidnight($pn_hour, $pn_minute, $pn_second) / 86400;
                     if ($hn_partday >= $hn_midyear - $hn_days) {
                         // Round up:
                         //
                         $hn_year = $pn_year + 1;
                     } else {
                         $hn_year = $pn_year;
                     }
                 }
             }
         }
     } else {
         if ($pn_precision == DATE_PRECISION_MONTH) {
             $hn_year = $pn_year;
             $hn_day = 0;
             $hn_hour = 0;
             $hn_minute = 0;
             $hn_second = 0;
             $hn_firstofmonth = Date_Calc::firstDayOfMonth($pn_month, $pn_year);
             $hn_midmonth = (Date_Calc::lastDayOfMonth($pn_month, $pn_year) + 1 - $hn_firstofmonth) / 2;
             if (($hn_days = Date_Calc::dateToDays($pn_day, $pn_month, $pn_year) - $hn_firstofmonth) <= $hn_midmonth - 1) {
                 $hn_month = $pn_month;
             } else {
                 if ($hn_days >= $hn_midmonth) {
                     // Round up:
                     //
                     list($hn_year, $hn_month) = Date_Calc::nextMonth($pn_month, $pn_year);
                 } else {
                     // Take time into account:
                     //
                     $hn_partday = Date_Calc::secondsPastMidnight($pn_hour, $pn_minute, $pn_second) / 86400;
                     if ($hn_partday >= $hn_midmonth - $hn_days) {
                         // Round up:
                         //
                         list($hn_year, $hn_month) = Date_Calc::nextMonth($pn_month, $pn_year);
                     } else {
                         $hn_month = $pn_month;
                     }
                 }
             }
         } else {
             if ($pn_precision == DATE_PRECISION_DAY) {
                 $hn_year = $pn_year;
                 $hn_month = $pn_month;
                 $hn_hour = 0;
                 $hn_minute = 0;
                 $hn_second = 0;
                 if (Date_Calc::secondsPastMidnight($pn_hour, $pn_minute, $pn_second) >= 43200) {
                     // Round up:
                     //
                     list($hn_year, $hn_month, $hn_day) = explode(" ", Date_Calc::nextDay($pn_day, $pn_month, $pn_year, "%Y %m %d"));
                 } else {
                     $hn_day = $pn_day;
                 }
             } else {
                 if ($pn_precision == DATE_PRECISION_HOUR) {
                     $hn_year = $pn_year;
                     $hn_month = $pn_month;
                     $hn_day = $pn_day;
                     $hn_minute = 0;
                     $hn_second = 0;
                     if (Date_Calc::secondsPastTheHour($pn_minute, $pn_second) >= 1800) {
                         // Round up:
                         //
                         list($hn_year, $hn_month, $hn_day, $hn_hour) = Date_Calc::addHours(1, $pn_day, $pn_month, $pn_year, $pn_hour);
                     } else {
                         $hn_hour = $pn_hour;
                     }
                 } else {
                     if ($pn_precision <= DATE_PRECISION_MINUTE) {
                         $hn_year = $pn_year;
                         $hn_month = $pn_month;
                         $hn_day = $pn_day;
                         $hn_hour = $pn_hour;
                         $hn_second = 0;
                         if ($pn_precision < DATE_PRECISION_MINUTE) {
                             $hn_minute = round($pn_minute, $pn_precision - DATE_PRECISION_MINUTE);
                         } else {
                             // Check seconds:
                             //
                             if ($pn_second >= 30) {
                                 // Round up:
                                 //
                                 list($hn_year, $hn_month, $hn_day, $hn_hour, $hn_minute) = Date_Calc::addMinutes(1, $pn_day, $pn_month, $pn_year, $pn_hour, $pn_minute);
                             } else {
                                 $hn_minute = $pn_minute;
                             }
                         }
                     } else {
                         // Precision is at least (DATE_PRECISION_SECOND - 1):
                         //
                         $hn_year = $pn_year;
                         $hn_month = $pn_month;
                         $hn_day = $pn_day;
                         $hn_hour = $pn_hour;
                         $hn_minute = $pn_minute;
                         $hn_second = round($pn_second, $pn_precision - DATE_PRECISION_SECOND);
                         if (fmod($hn_second, 1) == 0.0) {
                             $hn_second = (int) $hn_second;
                             if ($hn_second != intval($pn_second)) {
                                 list($hn_year, $hn_month, $hn_day, $hn_hour, $hn_minute, $hn_second) = Date_Calc::addSeconds($hn_second - intval($pn_second), $pn_day, $pn_month, $pn_year, $pn_hour, $pn_minute, intval($pn_second), $pn_precision >= DATE_PRECISION_SECOND && $pb_countleap);
                                 //
                                 // (N.B. if rounded to nearest 10 seconds,
                                 // user does not expect seconds to be '60')
                             }
                         }
                     }
                 }
             }
         }
     }
     return array((int) $hn_year, (int) $hn_month, (int) $hn_day, (int) $hn_hour, (int) $hn_minute, $hn_second);
 }
Ejemplo n.º 2
0
 /**
  * Sets the date/time of the object based on the input date and format
  *
  * Accepts a string in three possible formats, and in this order of
  * precedence:
  *
  *   - ISO 8601 date (see {@link http://en.wikipedia.org/wiki/ISO_8601})
  *   - Time-Stamp (i.e. 'YYYYMMDDHHMMSS')
  *   - Unix time-stamp (see {@link http://en.wikipedia.org/wiki/Unix_time})
  *
  * Note that if you want to pass a Unix time-stamp then you need to set
  * the $format parameter to {@link DATE_FORMAT_UNIXTIME}, or else use the
  * method {@link Date::setFromTime()}.
  *
  * The input string should be a date/time representation in one of the
  * following general formats:
  *
  *   - <b><date>T<time><time-zone></b>
  *   - <b><date> <time><time-zone></b> (non-ISO-standard)
  *   - <b><date><time><time-zone></b> (non-ISO-standard)
  *   - <b><date>T<time></b> i.e. without optional <time-zone> representation
  *   - <b><date> <time></b>
  *   - <b><date><time></b>
  *   - <b><date></b> i.e. without optional <time> representation
  *
  * that is, the representation must be comprised of a <b><date></b> part,
  * with an optional <b><time></b> part, which itself may include an optional
  * <time-zone> part, each of which may consist of any one of the permitted
  * formats detailed below.  The <b><date></b> and <b><time</b> representations
  * should be divided with the time designator <b>T</b> according to the ISO 8601
  * standard, although this method also permits representations divided by a
  * space, or by no delimiter at all.
  *
  * The <b><date></b> representation should be in one of the following formats:
  *
  *   - <b>Calendar date</b>: <b>YYYY-MM-DD</b> (extended format) or
  *                           <b>YYYYMMDD</b> (basic format), where [YYYY]
  *                           indicates the four-digit year (0000-9999), [MM]
  *                           indicates the month (01-12) and [DD] indicates the
  *                           day of the month [01-31]
  *   - <b>ISO week date</b>: <b>YYYY-Www-D</b> (extended format) or
  *                           <b>YYYYWwwD</b> (basic format), where [YYYY]
  *                           indicates the ISO year (slightly different from the
  *                           calendar year (see below)), [Www] indicates the ISO
  *                           week no prefixed by the letter 'W' (W01-W53) and
  *                           [D] indicates the ISO week-day (1-7), beginning on
  *                           Monday and ending on Sunday.  (Also see
  *                           {@link http://en.wikipedia.org/wiki/ISO_week_date}.)
  *   - <b>Ordinal date</b>: <b>YYYY-DDD</b> (extended format) or
  *                          <b>YYYYDDD</b> (basic format), where [YYYY]
  *                          indicates the four-digit year (0000-9999) and [DDD]
  *                          indicates the day of the year (001-366)
  *
  * The <b><time></b> representation should be in one of the following formats:
  *
  *   - <b>hh:mm:ss</b> (extended format) or <b>hhmmss</b> (basic format)
  *   - <b>hh:mm</b> (extended format) or <b>hhmm</b> (basic format)
  *   - <b>hh</b> (extended format) or <b>hh</b> (basic format)
  *
  * where [hh] represents the hour (00-24), [mm] represents the minute (00-59)
  * and [ss] represents the second (00-60)
  *
  * Format parameter should be one of the specified DATE_FORMAT_* constants:
  *
  *   - <b>{@link DATE_FORMAT_ISO}</b> - 'YYYY-MM-DD HH:MI:SS'
  *   - <b>{@link DATE_FORMAT_ISO_BASIC}</b> - 'YYYYMMDDTHHMMSS(Z|(+/-)HHMM)?'
  *   - <b>{@link DATE_FORMAT_ISO_EXTENDED}</b> - 'YYYY-MM-DDTHH:MM:SS(Z|(+/-)HH:MM)?'
  *   - <b>{@link DATE_FORMAT_ISO_EXTENDED_MICROTIME}</b> - 'YYYY-MM-DDTHH:MM:SS(.S*)?(Z|(+/-)HH:MM)?'
  *   - <b>{@link DATE_FORMAT_TIMESTAMP}</b> - 'YYYYMMDDHHMMSS'
  *   - <b>{@link DATE_FORMAT_UNIXTIME}</b> - 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 (for
  *                                        which use
  *                                        {@link DATE_FORMAT_UNIXTIME}).
  *                                        (Defaults to
  *                                        {@link DATE_FORMAT_ISO}.)
  * @param bool   $pb_repeatedhourdefault value to return if repeated
  *                                        hour is specified (defaults
  *                                        to false)
  *
  * @return   void
  * @access   public
  * @see      Date::isNull(), Date::isValidDate(), Date::isValidTime(),
  *            Date::setFromTime()
  */
 function setDate($date, $format = DATE_FORMAT_ISO, $pb_repeatedhourdefault = false)
 {
     if ($format == DATE_FORMAT_UNIXTIME) {
         if (is_numeric($date)) {
             // Assume Unix time-stamp:
             //
             $this->setFromTime((int) $date);
         } else {
             return PEAR::raiseError("'{$date}' not valid Unix time-stamp");
         }
     } else {
         if (preg_match('/^([0-9]{4,4})-?(' . '(0[1-9]|1[0-2])-?(0[1-9]|[12][0-9]|3[01])|' . 'W(0[1-9]|[1-4][0-9]|5[0-3])-?([1-7])|' . '(0(0[1-9]|[1-9][0-9])|[12][0-9]{2,2}|3([0-5][0-9]|6[1-6]))' . ')([T\\s]?' . '([01][0-9]|2[0-3])(:?' . '([0-5][0-9])(:?' . '([0-5][0-9]|60)([,.][0-9]+)?)?)?' . '(Z|[+\\-][0-9]{2,2}(:?[0-5][0-9])?)?)?$/i', $date, $regs)) {
             if (substr($regs[2], 0, 1) == "W") {
                 // ISO week date (YYYY-Www-D)
                 //
                 $hs_date = Date_Calc::isoWeekToDate($regs[6], $regs[5], $regs[1], "%Y %m %d");
                 if (PEAR::isError($hs_date)) {
                     return $hs_date;
                 }
                 list($hs_year, $hs_month, $hs_day) = explode(" ", $hs_date);
             } else {
                 if (strlen($regs[2]) == 3) {
                     // ISO ordinal date (YYYY-DDD)
                     //
                     $hn_jd = Date_Calc::firstDayOfYear($regs[1]) + $regs[2] - 1;
                     list($hs_year, $hs_month, $hs_day) = explode(" ", Date_Calc::daysToDate($hn_jd, "%Y %m %d"));
                 } else {
                     // ISO calendar date (YYYY-MM-DD)
                     //
                     // 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.
                     //
                     $hs_year = $regs[1];
                     $hs_month = $regs[3];
                     $hs_day = $regs[4];
                     if (!Date_Calc::isValidDate($hs_day, $hs_month, $hs_year)) {
                         return PEAR::raiseError("'" . Date_Calc::dateFormat($hs_year, $hs_month, $hs_day, "%Y-%m-%d") . "' is invalid calendar date", DATE_ERROR_INVALIDDATE);
                     }
                 }
             }
             if (isset($regs[17])) {
                 if ($regs[17] == "Z") {
                     $this->tz = new Date_TimeZone("UTC");
                 } else {
                     $this->tz = new Date_TimeZone("UTC" . $regs[17]);
                 }
             }
             $this->setLocalTime($hs_day, $hs_month, $hs_year, isset($regs[11]) && $regs[11] != "" ? $regs[11] : 0, isset($regs[13]) && $regs[13] != "" ? $regs[13] : 0, isset($regs[15]) && $regs[15] != "" ? $regs[15] : 0, isset($regs[16]) && $regs[16] != "" ? $regs[16] : 0.0, $pb_repeatedhourdefault);
         } else {
             return PEAR::raiseError("Date '{$date}' not in ISO 8601 format", DATE_ERROR_INVALIDDATEFORMAT);
         }
     }
 }