home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 April / CMCD0404.ISO / Software / Freeware / Programare / dotproject / lib / PEAR / Date.php < prev   
PHP Script  |  2003-05-29  |  37KB  |  1,143 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Baba Buehler <baba@babaz.com>                               |
  17. // |                                                                      |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // PEAR CVS Id: Date.php,v 1.12 2003/04/27 03:42:17 llucax Exp
  21. //
  22. // Date Class
  23. //
  24.  
  25. // dotProject CVS $Id: Date.php,v 1.6 2003/05/28 23:02:55 eddieajau Exp $
  26. // The following lines are modified to correctly load the libraries
  27. // from the dotProject distribution
  28. require_once( $AppUI->getLibraryClass( 'PEAR/Date/TimeZone' ) );
  29. require_once( $AppUI->getLibraryClass( 'PEAR/Date/Calc' ) );
  30. require_once( $AppUI->getLibraryClass( 'PEAR/Date/Span' ) );
  31.  
  32. /**
  33. * "YYYY-MM-DD HH:MM:SS"
  34. */
  35. define('DATE_FORMAT_ISO', 1);
  36. /**
  37. * "YYYYMMDDHHMMSS"
  38. */
  39. define('DATE_FORMAT_TIMESTAMP', 2);
  40. /**
  41. * long int, seconds since the unix epoch
  42. */
  43. define('DATE_FORMAT_UNIXTIME', 3);
  44.  
  45. /**
  46. * Generic date handling class for PEAR.
  47. *
  48. * Generic date handling class for PEAR.  Attempts to be time zone aware
  49. * through the Date::TimeZone class.  Supports several operations from
  50. * Date::Calc on Date objects.
  51. *
  52. * @author Baba Buehler <baba@babaz.com>
  53. * @package Date
  54. * @access public
  55. * @version 1.1
  56. */
  57. class Date
  58. {
  59.     /**
  60.      * the year
  61.      * @var int
  62.      */
  63.     var $year;
  64.     /**
  65.      * the month
  66.      * @var int
  67.      */
  68.     var $month;
  69.     /**
  70.      * the day
  71.      * @var int
  72.      */
  73.     var $day;
  74.     /**
  75.      * the hour
  76.      * @var int
  77.      */
  78.     var $hour;
  79.     /**
  80.      * the minute
  81.      * @var int
  82.      */
  83.     var $minute;
  84.     /**
  85.      * the second
  86.      * @var int
  87.      */
  88.     var $second;
  89.     /**
  90.      * timezone for this date
  91.      * @var object Date_TimeZone
  92.      */
  93.     var $tz;
  94.  
  95.  
  96.     /**
  97.      * Constructor
  98.      *
  99.      * Creates a new Date Object
  100.      * initialized to the current date/time in the
  101.      * system default time zone by default.  A date optionally
  102.      * passed in may be in the ISO, TIMESTAMP or UNIXTIME format,
  103.      * or another Date object.
  104.      *
  105.      * @access public
  106.      * @param mixed $date optional - date/time to initialize
  107.      * @return object Date the new Date object
  108.      */
  109.     function Date($date = null)
  110.     {
  111.         $this->tz = Date_TimeZone::getDefault();
  112.         if (is_null($date)) {
  113.             $this->setDate(date('Y-m-d H:i:s'));
  114. // following line has been modified by Andrew Eddie to support extending the Date class
  115.         //} elseif (is_object($date) && (get_class($date) == 'date')) {
  116.         } elseif (is_object($date) && (get_class($date) == get_class($this))) {
  117.             $this->copy($date);
  118.         } elseif (preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $date)) {
  119.             $this->setDate($date);
  120.         } elseif (preg_match('/\d{14}/',$date)) {
  121.             $this->setDate($date,DATE_FORMAT_TIMESTAMP);
  122.         } elseif (preg_match('/\d{4}-\d{2}-\d{2}/', $date)) {
  123.             $this->setDate($date.' 00:00:00');
  124.         } elseif (preg_match('/\d{8}/',$date)) {
  125.             $this->setDate($date.'000000',DATE_FORMAT_TIMESTAMP);
  126.         } else {
  127.             $this->setDate($date,DATE_FORMAT_UNIXTIME);
  128.         }
  129.     }
  130.  
  131.     /**
  132.      * Set the fields of a Date object based on the input date and format
  133.      *
  134.      * Set the fields of a Date object based on the input date and format,
  135.      * which is specified by the DATE_FORMAT_* constants.
  136.      *
  137.      * @access public
  138.      * @param string $date input date
  139.      * @param int $format format constant (DATE_FORMAT_*) of the input date
  140.      */
  141.     function setDate($date, $format = DATE_FORMAT_ISO)
  142.     {
  143.         switch($format) {
  144.             case DATE_FORMAT_ISO:
  145.                 if (ereg("([0-9]{4})-([0-9]{2})-([0-9]{2})[ ]([0-9]{2}):([0-9]{2}):([0-9]{2})",$date,$regs)) {
  146.                     $this->year   = $regs[1];
  147.                     $this->month  = $regs[2];
  148.                     $this->day    = $regs[3];
  149.                     $this->hour   = $regs[4];
  150.                     $this->minute = $regs[5];
  151.                     $this->second = $regs[6];
  152.                 } else {
  153.                     $this->year   = 0;
  154.                     $this->month  = 1;
  155.                     $this->day    = 1;
  156.                     $this->hour   = 0;
  157.                     $this->minute = 0;
  158.                     $this->second = 0;
  159.                 }
  160.                 break;
  161.             case DATE_FORMAT_TIMESTAMP:
  162.                 if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})",$date,$regs)) {
  163.                     $this->year   = $regs[1];
  164.                     $this->month  = $regs[2];
  165.                     $this->day    = $regs[3];
  166.                     $this->hour   = $regs[4];
  167.                     $this->minute = $regs[5];
  168.                     $this->second = $regs[6];
  169.                 } else {
  170.                     $this->year   = 0;
  171.                     $this->month  = 1;
  172.                     $this->day    = 1;
  173.                     $this->hour   = 0;
  174.                     $this->minute = 0;
  175.                     $this->second = 0;
  176.                 }
  177.                 break;
  178.             case DATE_FORMAT_UNIXTIME:
  179.                 $this->setDate(date("Y-m-d H:i:s", $date));
  180.                 break;
  181.         }
  182.     }
  183.  
  184.     /**
  185.      * Get a string (or other) representation of this date
  186.      *
  187.      * Get a string (or other) representation of this date in the
  188.      * format specified by the DATE_FORMAT_* constants.
  189.      *
  190.      * @access public
  191.      * @param int $format format constant (DATE_FORMAT_*) of the output date
  192.      * @return string the date in the requested format
  193.      */
  194.     function getDate($format = DATE_FORMAT_ISO)
  195.     {
  196.         switch($format) {
  197.             case DATE_FORMAT_ISO:
  198.                 return $this->format("%Y-%m-%d %T");
  199.                 break;
  200.             case DATE_FORMAT_TIMESTAMP:
  201.                 return $this->format("%Y%m%d%H%M%S");
  202.                 break;
  203.             case DATE_FORMAT_UNIXTIME:
  204.                 return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year, 0);
  205.                 break;
  206.         }
  207.     }
  208.  
  209.     /**
  210.      * Copy values from another Date object
  211.      *
  212.      * Makes this Date a copy of another Date object.
  213.      *
  214.      * @access public
  215.      * @param object Date $date Date to copy from
  216.      */
  217.     function copy($date)
  218.     {
  219.         $this->year = $date->year;
  220.         $this->month = $date->month;
  221.         $this->day = $date->day;
  222.         $this->hour = $date->hour;
  223.         $this->minute = $date->minute;
  224.         $this->second = $date->second;
  225.         $this->tz = $date->tz;
  226.     }
  227.  
  228.     /**
  229.      *  Date pretty printing, similar to strftime()
  230.      *
  231.      *  Formats the date in the given format, much like
  232.      *  strftime().  Most strftime() options are supported.<br><br>
  233.      *
  234.      *  formatting options:<br><br>
  235.      *
  236.      *  <code>%a  </code>  abbreviated weekday name (Sun, Mon, Tue) <br>
  237.      *  <code>%A  </code>  full weekday name (Sunday, Monday, Tuesday) <br>
  238.      *  <code>%b  </code>  abbreviated month name (Jan, Feb, Mar) <br>
  239.      *  <code>%B  </code>  full month name (January, February, March) <br>
  240.      *  <code>%C  </code>  century number (the year divided by 100 and truncated to an integer, range 00 to 99) <br>
  241.      *  <code>%d  </code>  day of month (range 00 to 31) <br>
  242.      *  <code>%D  </code>  same as "%m/%d/%y" <br>
  243.      *  <code>%e  </code>  day of month, single digit (range 0 to 31) <br>
  244.      *  <code>%E  </code>  number of days since unspecified epoch (integer, Date_Calc::dateToDays()) <br>
  245.      *  <code>%H  </code>  hour as decimal number (00 to 23) <br>
  246.      *  <code>%I  </code>  hour as decimal number on 12-hour clock (01 to 12) <br>
  247.      *  <code>%j  </code>  day of year (range 001 to 366) <br>
  248.      *  <code>%m  </code>  month as decimal number (range 01 to 12) <br>
  249.      *  <code>%M  </code>  minute as a decimal number (00 to 59) <br>
  250.      *  <code>%n  </code>  newline character (\n) <br>
  251.      *  <code>%O  </code>  dst-corrected timezone offset expressed as "+/-HH:MM" <br>
  252.      *  <code>%o  </code>  raw timezone offset expressed as "+/-HH:MM" <br>
  253.      *  <code>%p  </code>  either 'am' or 'pm' depending on the time <br>
  254.      *  <code>%P  </code>  either 'AM' or 'PM' depending on the time <br>
  255.      *  <code>%r  </code>  time in am/pm notation, same as "%I:%M:%S %p" <br>
  256.      *  <code>%R  </code>  time in 24-hour notation, same as "%H:%M" <br>
  257.      *  <code>%S  </code>  seconds as a decimal number (00 to 59) <br>
  258.      *  <code>%t  </code>  tab character (\t) <br>
  259.      *  <code>%T  </code>  current time, same as "%H:%M:%S" <br>
  260.      *  <code>%w  </code>  weekday as decimal (0 = Sunday) <br>
  261.      *  <code>%U  </code>  week number of current year, first sunday as first week <br>
  262.      *  <code>%y  </code>  year as decimal (range 00 to 99) <br>
  263.      *  <code>%Y  </code>  year as decimal including century (range 0000 to 9999) <br>
  264.      *  <code>%%  </code>  literal '%' <br>
  265.      * <br>
  266.      *
  267.      * @access public
  268.      * @param string format the format string for returned date/time
  269.      * @return string date/time in given format
  270.      */
  271.     function format($format)
  272.     {
  273.         $output = "";
  274.  
  275.         for($strpos = 0; $strpos < strlen($format); $strpos++) {
  276.             $char = substr($format,$strpos,1);
  277.             if($char == "%") {
  278.                 $nextchar = substr($format,$strpos + 1,1);
  279.                 switch($nextchar) {
  280.                     case "a":
  281.                         $output .= Date_Calc::getWeekdayAbbrname($this->day,$this->month,$this->year);
  282.                         break;
  283.                     case "A":
  284.                         $output .= Date_Calc::getWeekdayFullname($this->day,$this->month,$this->year);
  285.                         break;
  286.                     case "b":
  287.                         $output .= Date_Calc::getMonthAbbrname($this->month);
  288.                         break;
  289.                     case "B":
  290.                         $output .= Date_Calc::getMonthFullname($this->month);
  291.                         break;
  292.                     case "C":
  293.                         $output .= sprintf("%02d",intval($this->year/100));
  294.                         break;
  295.                     case "d":
  296.                         $output .= sprintf("%02d",$this->day);
  297.                         break;
  298.                     case "D":
  299.                         $output .= sprintf("%02d/%02d/%02d",$this->month,$this->day,$this->year);
  300.                         break;
  301.                     case "e":
  302.                         $output .= $this->day;
  303.                         break;
  304.                     case "E":
  305.                         $output .= Date_Calc::dateToDays($this->day,$this->month,$this->year);
  306.                         break;
  307.                     case "H":
  308.                         $output .= sprintf("%02d", $this->hour);
  309.                         break;
  310.                     case "I":
  311.                         $hour = ($this->hour + 1) > 12 ? $this->hour - 12 : $this->hour;
  312.                         $output .= sprintf("%02d", $hour==0 ? 12 : $hour);
  313.                         break;
  314.                     case "j":
  315.                         $output .= Date_Calc::julianDate($this->day,$this->month,$this->year);
  316.                         break;
  317.                     case "m":
  318.                         $output .= sprintf("%02d",$this->month);
  319.                         break;
  320.                     case "M":
  321.                         $output .= sprintf("%02d",$this->minute);
  322.                         break;
  323.                     case "n":
  324.                         $output .= "\n";
  325.                         break;
  326.                     case "O":
  327.                         $offms = $this->tz->getOffset($this);
  328.                         $direction = $offms >= 0 ? "+" : "-";
  329.                         $offmins = abs($offms) / 1000 / 60;
  330.                         $hours = $offmins / 60;
  331.                         $minutes = $offmins % 60;
  332.                         $output .= sprintf("%s%02d:%02d", $direction, $hours, $minutes);
  333.                         break;
  334.                     case "o":
  335.                         $offms = $this->tz->getRawOffset($this);
  336.                         $direction = $offms >= 0 ? "+" : "-";
  337.                         $offmins = abs($offms) / 1000 / 60;
  338.                         $hours = $offmins / 60;
  339.                         $minutes = $offmins % 60;
  340.                         $output .= sprintf("%s%02d:%02d", $direction, $hours, $minutes);
  341.                         break;
  342.                     case "p":
  343.                         $output .= $this->hour >= 12 ? "pm" : "am";
  344.                         break;
  345.                     case "P":
  346.                         $output .= $this->hour >= 12 ? "PM" : "AM";
  347.                         break;
  348.                     case "r":
  349.                         $hour = ($this->hour + 1) > 12 ? $this->hour - 12 : $this->hour;
  350.                         $output .= sprintf("%02d:%02d:%02d %s", $hour==0 ?  12 : $hour, $this->minute, $this->second, $this->hour >= 12 ? "PM" : "AM");
  351.                         break;
  352.                     case "R":
  353.                         $output .= sprintf("%02d:%02d", $this->hour, $this->minute);
  354.                         break;
  355.                     case "S":
  356.                         $output .= sprintf("%02d", $this->second);
  357.                         break;
  358.                     case "t":
  359.                         $output .= "\t";
  360.                         break;
  361.                     case "T":
  362.                         $output .= sprintf("%02d:%02d:%02d", $this->hour, $this->minute, $this->second);
  363.                         break;
  364.                     case "w":
  365.                         $output .= Date_Calc::dayOfWeek($this->day,$this->month,$this->year);
  366.                         break;
  367.                     case "U":
  368.                         $output .= Date_Calc::weekOfYear($this->day,$this->month,$this->year);
  369.                         break;
  370.                     case "y":
  371.                         $output .= substr($this->year,2,2);
  372.                         break;
  373.                     case "Y":
  374.                         $output .= $this->year;
  375.                         break;
  376.                     case "Z":
  377.                         $output .= $this->tz->inDaylightTime($this) ? $this->tz->getDSTShortName() : $this->tz->getShortName();
  378.                         break;
  379.                     case "%":
  380.                         $output .= "%";
  381.                         break;
  382.                     default:
  383.                         $output .= $char.$nextchar;
  384.                 }
  385.                 $strpos++;
  386.             } else {
  387.                 $output .= $char;
  388.             }
  389.         }
  390.         return $output;
  391.  
  392.     }
  393.  
  394.     /**
  395.      * Get this date/time in Unix time() format
  396.      *
  397.      * Get a representation of this date in Unix time() format.  This may only be
  398.      * valid for dates from 1970 to ~2038.
  399.      *
  400.      * @access public
  401.      * @return int number of seconds since the unix epoch
  402.      */
  403.     function getTime()
  404.     {
  405.         return $this->getDate(DATE_FORMAT_UNIXTIME);
  406.     }
  407.  
  408.     /**
  409.      * Sets the time zone of this Date
  410.      *
  411.      * Sets the time zone of this date with the given
  412.      * Date_TimeZone object.  Does not alter the date/time,
  413.      * only assigns a new time zone.  For conversion, use
  414.      * convertTZ().
  415.      *
  416.      * @access public
  417.      * @param object Date_TimeZone $tz the Date_TimeZone object to use
  418.      */
  419.     function setTZ($tz)
  420.     {
  421.         $this->tz = $tz;
  422.     }
  423.  
  424.     /**
  425.      * Sets the time zone of this date with the given time zone id
  426.      *
  427.      * Sets the time zone of this date with the given
  428.      * time zone id, or to the system default if the
  429.      * given id is invalid. Does not alter the date/time,
  430.      * only assigns a new time zone.  For conversion, use
  431.      * convertTZ().
  432.      *
  433.      * @access public
  434.      * @param string id a time zone id
  435.      */
  436.     function setTZbyID($id)
  437.     {
  438.         if(Date_TimeZone::isValidID($id)) {
  439.             $this->tz = new Date_TimeZone($id);
  440.         } else {
  441.             $this->tz = Date_TimeZone::getDefault();
  442.         }
  443.     }
  444.  
  445.     /**
  446.      * Tests if this date/time is in DST
  447.      *
  448.      * Returns true if daylight savings time is in effect for
  449.      * this date in this date's time zone.  See Date_TimeZone::inDaylightTime()
  450.      * for compatability information.
  451.      *
  452.      * @access public
  453.      * @return boolean true if DST is in effect for this date
  454.      */
  455.     function inDaylightTime()
  456.     {
  457.         return $this->tz->inDaylightTime($this);
  458.     }
  459.  
  460.     /**
  461.      * Converts this date to UTC and sets this date's timezone to UTC
  462.      *
  463.      * Converts this date to UTC and sets this date's timezone to UTC
  464.      *
  465.      * @access public
  466.      */
  467.     function toUTC()
  468.     {
  469.         if($this->tz->getOffset($this) > 0) {
  470.             $this->subtractSeconds(intval($this->tz->getOffset($this) / 1000));
  471.         } else {
  472.             $this->addSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
  473.         }
  474.         $this->tz = new Date_TimeZone('UTC');
  475.     }
  476.  
  477.     /**
  478.      * Converts this date to a new time zone
  479.      *
  480.      * Converts this date to a new time zone.
  481.      * WARNING: This may not work correctly if your system does not allow
  482.      * putenv() or if localtime() does not work in your environment.  See
  483.      * Date::TimeZone::inDaylightTime() for more information.
  484.      *
  485.      * @access public
  486.      * @param object Date_TimeZone $tz the Date::TimeZone object for the conversion time zone
  487.      */
  488.     function convertTZ($tz)
  489.     {
  490.         // convert to UTC
  491.         if($this->tz->getOffset($this) > 0) {
  492.             $this->subtractSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
  493.         } else {
  494.             $this->addSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
  495.         }
  496.         // convert UTC to new timezone
  497.         if($tz->getOffset($this) > 0) {
  498.             $this->addSeconds(intval(abs($tz->getOffset($this)) / 1000));
  499.         } else {
  500.             $this->subtractSeconds(intval(abs($tz->getOffset($this)) / 1000));
  501.         }
  502.         $this->tz = $tz;
  503.     }
  504.  
  505.     /**
  506.      * Converts this date to a new time zone, given a valid time zone ID
  507.      *
  508.      * Converts this date to a new time zone, given a valid time zone ID
  509.      * WARNING: This may not work correctly if your system does not allow
  510.      * putenv() or if localtime() does not work in your environment.  See
  511.      * Date::TimeZone::inDaylightTime() for more information.
  512.      *
  513.      * @access public
  514.      * @param string id a time zone id
  515.      */
  516.     function convertTZbyID($id)
  517.     {
  518.        if(Date_TimeZone::isValidID($id)) {
  519.           $tz = new Date_TimeZone($id);
  520.        } else {
  521.           $tz = Date_TimeZone::getDefault();
  522.        }
  523.        $this->convertTZ($tz);
  524.     }
  525.  
  526.     /**
  527.      * Adds a given number of seconds to the date
  528.      *
  529.      * Adds a given number of seconds to the date
  530.      *
  531.      * @access public
  532.      * @param int $sec the number of seconds to add
  533.      */
  534.     function addSeconds($sec)
  535.     {
  536.         $this->addSpan(new Date_Span($sec));
  537.     }
  538.  
  539.     /**
  540.      * Adds a time span to the date
  541.      *
  542.      * Adds a time span to the date
  543.      *
  544.      * @access public
  545.      * @param object Date_Span $span the time span to add
  546.      */
  547.     function addSpan($span)
  548.     {
  549.         $this->second += $span->second;
  550.         if($this->second >= 60) {
  551.             $this->minute++;
  552.             $this->second -= 60;
  553.         }
  554.  
  555.         $this->minute += $span->minute;
  556.         if($this->minute >= 60) {
  557.             $this->hour++;
  558.             if($this->hour >= 24) {
  559.                 list($this->year, $this->month, $this->day) =
  560.                     sscanf(Date_Calc::nextDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  561.                 $this->hour -= 24;
  562.             }
  563.             $this->minute -= 60;
  564.         }
  565.  
  566.         $this->hour += $span->hour;
  567.         if($this->hour >= 24) {
  568.             list($this->year, $this->month, $this->day) =
  569.                 sscanf(Date_Calc::nextDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  570.             $this->hour -= 24;
  571.         }
  572.  
  573.         $d = Date_Calc::dateToDays($this->day, $this->month, $this->year);
  574.         $d += $span->day;
  575.  
  576.         list($this->year, $this->month, $this->day) =
  577.             sscanf(Date_Calc::daysToDate($d), "%04s%02s%02s");
  578.         $this->year  = intval($this->year);
  579.         $this->month = intval($this->month);
  580.         $this->day   = intval($this->day);
  581.     }
  582.  
  583.     /**
  584.      * Subtracts a given number of seconds from the date
  585.      *
  586.      * Subtracts a given number of seconds from the date
  587.      *
  588.      * @access public
  589.      * @param int $sec the number of seconds to subtract
  590.      */
  591.     function subtractSeconds($sec)
  592.     {
  593.         $this->subtractSpan(new Date_Span($sec));
  594.     }
  595.  
  596.     /**
  597.      * Subtracts a time span to the date
  598.      *
  599.      * Subtracts a time span to the date
  600.      *
  601.      * @access public
  602.      * @param object Date_Span $span the time span to subtract
  603.      */
  604.     function subtractSpan($span)
  605.     {
  606.         $this->second -= $span->second;
  607.         if($this->second < 0) {
  608.             $this->minute--;
  609.             $this->second += 60;
  610.         }
  611.  
  612.         $this->minute -= $span->minute;
  613.         if($this->minute < 0) {
  614.             $this->hour--;
  615.             if($this->hour < 0) {
  616.                 list($this->year, $this->month, $this->day) =
  617.                     sscanf(Date_Calc::prevDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  618.                 $this->hour += 24;
  619.             }
  620.             $this->minute += 60;
  621.         }
  622.  
  623.         $this->hour -= $span->hour;
  624.         if($this->hour < 0) {
  625.             list($this->year, $this->month, $this->day) =
  626.                 sscanf(Date_Calc::prevDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  627.             $this->hour += 24;
  628.         }
  629.  
  630.         $d = Date_Calc::dateToDays($this->day, $this->month, $this->year);
  631.         $d -= $span->day;
  632.  
  633.         list($this->year, $this->month, $this->day) =
  634.             sscanf(Date_Calc::daysToDate($d), "%04s%02s%02s");
  635.         $this->year  = intval($this->year);
  636.         $this->month = intval($this->month);
  637.         $this->day   = intval($this->day);
  638.     }
  639.  
  640.     /**
  641.      * Compares two dates
  642.      *
  643.      * Compares two dates.  Suitable for use
  644.      * in sorting functions.
  645.      *
  646.      * @access public
  647.      * @param object Date $d1 the first date
  648.      * @param object Date $d2 the second date
  649.      * @return int 0 if the dates are equal, -1 if d1 is before d2, 1 if d1 is after d2
  650.      */
  651.     function compare($d1, $d2)
  652.     {
  653.         $d1->convertTZ(new Date_TimeZone('UTC'));
  654.         $d2->convertTZ(new Date_TimeZone('UTC'));
  655.         $days1 = Date_Calc::dateToDays($d1->day, $d1->month, $d1->year);
  656.         $days2 = Date_Calc::dateToDays($d2->day, $d2->month, $d2->year);
  657.         if($days1 < $days2) return -1;
  658.         if($days1 > $days2) return 1;
  659.         if($d1->hour < $d2->hour) return -1;
  660.         if($d1->hour > $d2->hour) return 1;
  661.         if($d1->minute < $d2->minute) return -1;
  662.         if($d1->minute > $d2->minute) return 1;
  663.         if($d1->second < $d2->second) return -1;
  664.         if($d1->second > $d2->second) return 1;
  665.         return 0;
  666.     }
  667.  
  668.     /**
  669.      * Test if this date/time is before a certian date/time
  670.      *
  671.      * Test if this date/time is before a certian date/time
  672.      *
  673.      * @access public
  674.      * @param object Date $when the date to test against
  675.      * @return boolean true if this date is before $when
  676.      */
  677.     function before($when)
  678.     {
  679.         if($this->compare($this,$when) == -1) {
  680.             return true;
  681.         } else {
  682.             return false;
  683.         }
  684.     }
  685.  
  686.     /**
  687.      * Test if this date/time is after a certian date/time
  688.      *
  689.      * Test if this date/time is after a certian date/time
  690.      *
  691.      * @access public
  692.      * @param object Date $when the date to test against
  693.      * @return boolean true if this date is after $when
  694.      */
  695.     function after($when)
  696.     {
  697.         if($this->compare($this,$when) == 1) {
  698.             return true;
  699.         } else {
  700.             return false;
  701.         }
  702.     }
  703.  
  704.     /**
  705.      * Test if this date/time is exactly equal to a certian date/time
  706.      *
  707.      * Test if this date/time is exactly equal to a certian date/time
  708.      *
  709.      * @access public
  710.      * @param object Date $when the date to test against
  711.      * @return boolean true if this date is exactly equal to $when
  712.      */
  713.     function equals($when)
  714.     {
  715.         if($this->compare($this,$when) == 0) {
  716.             return true;
  717.         } else {
  718.             return false;
  719.         }
  720.     }
  721.  
  722.     /**
  723.      * Determine if this date is in the future
  724.      *
  725.      * Determine if this date is in the future
  726.      *
  727.      * @access public
  728.      * @return boolean true if this date is in the future
  729.      */
  730.     function isFuture()
  731.     {
  732.         $now = new Date();
  733.         if($this->after($now)) {
  734.             return true;
  735.         } else {
  736.             return false;
  737.         }
  738.     }
  739.  
  740.     /**
  741.      * Determine if this date is in the past
  742.      *
  743.      * Determine if this date is in the past
  744.      *
  745.      * @access public
  746.      * @return boolean true if this date is in the past
  747.      */
  748.     function isPast()
  749.     {
  750.         $now = new Date();
  751.         if($this->before($now)) {
  752.             return true;
  753.         } else {
  754.             return false;
  755.         }
  756.     }
  757.  
  758.     /**
  759.      * Determine if the year in this date is a leap year
  760.      *
  761.      * Determine if the year in this date is a leap year
  762.      *
  763.      * @access public
  764.      * @return boolean true if this year is a leap year
  765.      */
  766.     function isLeapYear()
  767.     {
  768.         return Date_Calc::isLeapYear($this->year);
  769.     }
  770.  
  771.     /**
  772.      * Get the Julian date for this date
  773.      *
  774.      * Get the Julian date for this date
  775.      *
  776.      * @access public
  777.      * @return int the Julian date
  778.      */
  779.     function getJulianDate()
  780.     {
  781.         return Date_Calc::julianDate($this->day, $this->month, $this->year);
  782.     }
  783.  
  784.     /**
  785.      * Gets the day of the week for this date
  786.      *
  787.      * Gets the day of the week for this date (0=Sunday)
  788.      *
  789.      * @access public
  790.      * @return int the day of the week (0=Sunday)
  791.      */
  792.     function getDayOfWeek()
  793.     {
  794.         return Date_Calc::dayOfWeek($this->day, $this->month, $this->year);
  795.     }
  796.  
  797.     /**
  798.      * Gets the week of the year for this date
  799.      *
  800.      * Gets the week of the year for this date
  801.      *
  802.      * @access public
  803.      * @return int the week of the year
  804.      */
  805.     function getWeekOfYear()
  806.     {
  807.         return Date_Calc::weekOfYear($this->day, $this->month, $this->year);
  808.     }
  809.  
  810.     /**
  811.      * Gets the quarter of the year for this date
  812.      *
  813.      * Gets the quarter of the year for this date
  814.      *
  815.      * @access public
  816.      * @return int the quarter of the year (1-4)
  817.      */
  818.     function getQuarterOfYear()
  819.     {
  820.         return Date_Calc::quarterOfYear($this->day, $this->month, $this->year);
  821.     }
  822.  
  823.     /**
  824.      * Gets number of days in the month for this date
  825.      *
  826.      * Gets number of days in the month for this date
  827.      *
  828.      * @access public
  829.      * @return int number of days in this month
  830.      */
  831.     function getDaysInMonth()
  832.     {
  833.         return Date_Calc::daysInMonth($this->month, $this->year);
  834.     }
  835.  
  836.     /**
  837.      * Gets the number of weeks in the month for this date
  838.      *
  839.      * Gets the number of weeks in the month for this date
  840.      *
  841.      * @access public
  842.      * @return int number of weeks in this month
  843.      */
  844.     function getWeeksInMonth()
  845.     {
  846.         return Date_Calc::weeksInMonth($this->month, $this->year);
  847.     }
  848.  
  849.     /**
  850.      * Gets the full name or abbriviated name of this weekday
  851.      *
  852.      * Gets the full name or abbriviated name of this weekday
  853.      *
  854.      * @access public
  855.      * @param boolean $abbr abbrivate the name
  856.      * @return string name of this day
  857.      */
  858.     function getDayName($abbr = false)
  859.     {
  860.         if($abbr) {
  861.             return Date_Calc::getWeekdayAbbrname($this->day, $this->month, $this->year);
  862.         } else {
  863.             return Date_Calc::getWeekdayFullname($this->day, $this->month, $this->year);
  864.         }
  865.     }
  866.  
  867.     /**
  868.      * Gets the full name or abbriviated name of this month
  869.      *
  870.      * Gets the full name or abbriviated name of this month
  871.      *
  872.      * @access public
  873.      * @param boolean $abbr abbrivate the name
  874.      * @return string name of this month
  875.      */
  876.     function getMonthName($abbr = false)
  877.     {
  878.         if($abbr) {
  879.             return Date_Calc::getMonthAbbrname($this->month);
  880.         } else {
  881.             return Date_Calc::getMonthFullname($this->month);
  882.         }
  883.     }
  884.  
  885.     /**
  886.      * Get a Date object for the day after this one
  887.      *
  888.      * Get a Date object for the day after this one.
  889.      * The time of the returned Date object is the same as this time.
  890.      *
  891.      * @access public
  892.      * @return object Date Date representing the next day
  893.      */
  894.     function getNextDay()
  895.     {
  896.         $day = Date_Calc::nextDay($this->day, $this->month, $this->year, "%Y-%m-%d");
  897.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  898.         $newDate = new Date();
  899.         $newDate->setDate($date);
  900.         return $newDate;
  901.     }
  902.  
  903.     /**
  904.      * Get a Date object for the day before this one
  905.      *
  906.      * Get a Date object for the day before this one.
  907.      * The time of the returned Date object is the same as this time.
  908.      *
  909.      * @access public
  910.      * @return object Date Date representing the previous day
  911.      */
  912.     function getPrevDay()
  913.     {
  914.         $day = Date_Calc::prevDay($this->day, $this->month, $this->year, "%Y-%m-%d");
  915.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  916.         $newDate = new Date();
  917.         $newDate->setDate($date);
  918.         return $newDate;
  919.     }
  920.  
  921.     /**
  922.      * Get a Date object for the weekday after this one
  923.      *
  924.      * Get a Date object for the weekday after this one.
  925.      * The time of the returned Date object is the same as this time.
  926.      *
  927.      * @access public
  928.      * @return object Date Date representing the next weekday
  929.      */
  930.     function getNextWeekday()
  931.     {
  932.         $day = Date_Calc::nextWeekday($this->day, $this->month, $this->year, "%Y-%m-%d");
  933.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  934.         $newDate = new Date();
  935.         $newDate->setDate($date);
  936.         return $newDate;
  937.     }
  938.  
  939.     /**
  940.      * Get a Date object for the weekday before this one
  941.      *
  942.      * Get a Date object for the weekday before this one.
  943.      * The time of the returned Date object is the same as this time.
  944.      *
  945.      * @access public
  946.      * @return object Date Date representing the previous weekday
  947.      */
  948.     function getPrevWeekday()
  949.     {
  950.         $day = Date_Calc::prevWeekday($this->day, $this->month, $this->year, "%Y-%m-%d");
  951.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  952.         $newDate = new Date();
  953.         $newDate->setDate($date);
  954.         return $newDate;
  955.     }
  956.  
  957.  
  958.     /**
  959.      * Returns the year field of the date object
  960.      *
  961.      * Returns the year field of the date object
  962.      *
  963.      * @access public
  964.      * @return int the year
  965.      */
  966.     function getYear()
  967.     {
  968.         return $this->year;
  969.     }
  970.  
  971.     /**
  972.      * Returns the month field of the date object
  973.      *
  974.      * Returns the month field of the date object
  975.      *
  976.      * @access public
  977.      * @return int the month
  978.      */
  979.     function getMonth()
  980.     {
  981.         return $this->month;
  982.     }
  983.  
  984.     /**
  985.      * Returns the day field of the date object
  986.      *
  987.      * Returns the day field of the date object
  988.      *
  989.      * @access public
  990.      * @return int the day
  991.      */
  992.     function getDay()
  993.     {
  994.         return $this->day;
  995.     }
  996.  
  997.     /**
  998.      * Returns the hour field of the date object
  999.      *
  1000.      * Returns the hour field of the date object
  1001.      *
  1002.      * @access public
  1003.      * @return int the hour
  1004.      */
  1005.     function getHour()
  1006.     {
  1007.         return $this->hour;
  1008.     }
  1009.  
  1010.     /**
  1011.      * Returns the minute field of the date object
  1012.      *
  1013.      * Returns the minute field of the date object
  1014.      *
  1015.      * @access public
  1016.      * @return int the minute
  1017.      */
  1018.     function getMinute()
  1019.     {
  1020.         return $this->minute;
  1021.     }
  1022.  
  1023.     /**
  1024.      * Returns the second field of the date object
  1025.      *
  1026.      * Returns the second field of the date object
  1027.      *
  1028.      * @access public
  1029.      * @return int the second
  1030.      */
  1031.     function getSecond()
  1032.     {
  1033.          return $this->second;
  1034.     }
  1035.  
  1036.     /**
  1037.      * Set the year field of the date object
  1038.      *
  1039.      * Set the year field of the date object, invalid years (not 0-9999) are set to 0.
  1040.      *
  1041.      * @access public
  1042.      * @param int $y the year
  1043.      */
  1044.     function setYear($y)
  1045.     {
  1046.         if($y < 0 || $y > 9999) {
  1047.             $this->year = 0;
  1048.         } else {
  1049.             $this->year = $y;
  1050.         }
  1051.     }
  1052.  
  1053.     /**
  1054.      * Set the month field of the date object
  1055.      *
  1056.      * Set the month field of the date object, invalid months (not 1-12) are set to 1.
  1057.      *
  1058.      * @access public
  1059.      * @param int $m the month
  1060.      */
  1061.     function setMonth($m)
  1062.     {
  1063.         if($m < 1 || $m > 12) {
  1064.             $this->month = 1;
  1065.         } else {
  1066.             $this->month = $m;
  1067.         }
  1068.     }
  1069.  
  1070.     /**
  1071.      * Set the day field of the date object
  1072.      *
  1073.      * Set the day field of the date object, invalid days (not 1-31) are set to 1.
  1074.      *
  1075.      * @access public
  1076.      * @param int $d the day
  1077.      */
  1078.     function setDay($d)
  1079.     {
  1080.         if($d > 31 || $d < 1) {
  1081.             $this->day = 1;
  1082.         } else {
  1083.             $this->day = $d;
  1084.         }
  1085.     }
  1086.  
  1087.     /**
  1088.      * Set the hour field of the date object
  1089.      *
  1090.      * Set the hour field of the date object in 24-hour format.
  1091.      * Invalid hours (not 0-23) are set to 0.
  1092.      *
  1093.      * @access public
  1094.      * @param int $h the hour
  1095.      */
  1096.     function setHour($h)
  1097.     {
  1098.         if($h > 23 || $h < 0) {
  1099.             $this->hour = 0;
  1100.         } else {
  1101.             $this->hour = $h;
  1102.         }
  1103.     }
  1104.  
  1105.     /**
  1106.      * Set the minute field of the date object
  1107.      *
  1108.      * Set the minute field of the date object, invalid minutes (not 0-59) are set to 0.
  1109.      *
  1110.      * @access public
  1111.      * @param int $m the minute
  1112.      */
  1113.     function setMinute($m)
  1114.     {
  1115.         if($m > 59 || $m < 0) {
  1116.             $this->minute = 0;
  1117.         } else {
  1118.             $this->minute = $m;
  1119.         }
  1120.     }
  1121.  
  1122.     /**
  1123.      * Set the second field of the date object
  1124.      *
  1125.      * Set the second field of the date object, invalid seconds (not 0-59) are set to 0.
  1126.      *
  1127.      * @access public
  1128.      * @param int $s the second
  1129.      */
  1130.     function setSecond($s) {
  1131.         if($s > 59 || $s < 0) {
  1132.             $this->second = 0;
  1133.         } else {
  1134.             $this->second = $s;
  1135.         }
  1136.     }
  1137.  
  1138. } // Date
  1139.  
  1140.  
  1141. //
  1142. // END
  1143. ?>