Source for file Timespan.class.php

Documentation is available at Timespan.class.php

  1. <?php
  2. /**
  3. * @since 5/2/05
  4. * @package harmoni.primitives.chronology
  5. *
  6. * @copyright Copyright &copy; 2005, Middlebury College
  7. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)
  8. *
  9. * @version $Id: Timespan.class.php,v 1.5 2007/09/04 20:25:25 adamfranco Exp $
  10. *
  11. * @link http://harmoni.sourceforge.net/
  12. * @author Adam Franco <adam AT adamfranco DOT com> <afranco AT middlebury DOT edu>
  13. */
  14.  
  15. require_once(dirname(__FILE__)."/../Magnitudes/Magnitude.class.php");
  16.  
  17. /**
  18. * Timespan represents a duration starting at a specific DateAndTime.
  19. *
  20. * To create new Timespan instances, <b>use one of the static instance-creation
  21. * methods</b>, NOT 'new Timespan':
  22. * - {@link current Timespan::current()}
  23. * - {@link current Timespan::current()}
  24. * - {@link epoch Timespan::epoch()}
  25. * - {@link starting Timespan::starting($aDateAndTime)}
  26. * - {@link startingDuration Timespan::startingDuration($aDateAndTime, $aDuration)}
  27. * - {@link startingEnding Timespan::startingEnding($startDateAndTime, $endDateAndTime)}
  28. *
  29. * @since 5/2/05
  30. * @package harmoni.primitives.chronology
  31. *
  32. * @copyright Copyright &copy; 2005, Middlebury College
  33. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)
  34. *
  35. * @version $Id: Timespan.class.php,v 1.5 2007/09/04 20:25:25 adamfranco Exp $
  36. *
  37. * @link http://harmoni.sourceforge.net/
  38. * @author Adam Franco <adam AT adamfranco DOT com> <afranco AT middlebury DOT edu>
  39. */
  40. class Timespan
  41. extends Magnitude
  42. {
  43.  
  44. /**
  45. * @var object DateAndTime $start; The starting point of this time-span
  46. * @access private
  47. * @since 5/11/05
  48. */
  49. var $start;
  50. /**
  51. * @var object Duration $duration; The duration of this time-span.
  52. * @access private
  53. * @since 5/11/05
  54. */
  55. var $duration;
  56.  
  57. /*******************************************************
  58. * Class Methods - Instance Creation
  59. *
  60. * All static instance creation methods have an optional
  61. * $class parameter which is used to get around the limitations
  62. * of not being able to find the class of the object that
  63. * recieved the initial method call rather than the one in
  64. * which it is implemented. These parameters SHOULD NOT BE
  65. * USED OUTSIDE OF THIS PACKAGE.
  66. *********************************************************/
  67.  
  68. /**
  69. * Answer a new object that represents now.
  70. *
  71. * @param optional string $class DO NOT USE OUTSIDE OF PACKAGE.
  72. * This parameter is used to get around the limitations of not being
  73. * able to find the class of the object that recieved the initial
  74. * method call.
  75. * @return object Timespan
  76. * @access public
  77. * @since 5/5/05
  78. * @static
  79. */
  80. function current ( $class = 'Timespan' ) {
  81. eval('$result = '.$class.'::starting(DateAndTime::now(), $class);');
  82. return $result;
  83. }
  84. /**
  85. * Answer a Timespan starting on the Squeak epoch: 1 January 1901
  86. *
  87. * @param optional string $class DO NOT USE OUTSIDE OF PACKAGE.
  88. * This parameter is used to get around the limitations of not being
  89. * able to find the class of the object that recieved the initial
  90. * method call.
  91. * @return object Timespan
  92. * @access public
  93. * @since 5/5/05
  94. * @static
  95. */
  96. function epoch ( $class = 'Timespan' ) {
  97. eval('$result = '.$class.'::starting(DateAndTime::epoch(), $class);');
  98. return $result;
  99. }
  100. /**
  101. * Create a new object starting now, with zero duration
  102. *
  103. * @param object DateAndTime $aDateAndTime
  104. * @param optional string $class DO NOT USE OUTSIDE OF PACKAGE.
  105. * This parameter is used to get around the limitations of not being
  106. * able to find the class of the object that recieved the initial
  107. * method call.
  108. * @return object Timespan
  109. * @access public
  110. * @since 5/5/05
  111. * @static
  112. */
  113. function starting ( $aDateAndTime, $class = 'Timespan' ) {
  114. eval('$result = '.$class.'::startingDuration(
  115. $aDateAndTime, Duration::zero(), $class);');
  116. return $result;
  117. }
  118. /**
  119. * Create a new object
  120. *
  121. * @param object DateAndTime $aDateAndTime
  122. * @param object Duration $aDuration
  123. * @param optional string $class DO NOT USE OUTSIDE OF PACKAGE.
  124. * This parameter is used to get around the limitations of not being
  125. * able to find the class of the object that recieved the initial
  126. * method call.
  127. * @return object Timespan
  128. * @access public
  129. * @since 5/5/05
  130. * @static
  131. */
  132. function startingDuration ( $aDateAndTime, $aDuration, $class = 'Timespan' ) {
  133. // Validate our passed class name.
  134. if (!(strtolower($class) == strtolower('Timespan')
  135. || is_subclass_of(new $class, 'Timespan')))
  136. {
  137. die("Class, '$class', is not a subclass of 'Timespan'.");
  138. }
  139. $timeSpan = new $class;
  140. $timeSpan->setStart($aDateAndTime);
  141. $timeSpan->setDuration($aDuration);
  142. return $timeSpan;
  143. }
  144. /**
  145. * Create a new object with given start and end DateAndTimes
  146. *
  147. * @param object DateAndTime $startDateAndTime
  148. * @param object DateAndTime $endDateAndTime
  149. * @param optional string $class DO NOT USE OUTSIDE OF PACKAGE.
  150. * This parameter is used to get around the limitations of not being
  151. * able to find the class of the object that recieved the initial
  152. * method call.
  153. * @return object Timespan
  154. * @access public
  155. * @since 5/11/05
  156. */
  157. function startingEnding ( $startDateAndTime, $endDateAndTime, $class = 'Timespan' )
  158. {
  159. $end =$endDateAndTime->asDateAndTime();
  160. eval('$result = '.$class.'::startingDuration(
  161. $startDateAndTime,
  162. $end->minus($startDateAndTime),
  163. $class);');
  164. return $result;
  165. }
  166. /*******************************************************
  167. * Instance Methods - Private
  168. *********************************************************/
  169.  
  170. /**
  171. * Do not use this constructor for building objects, please use the
  172. * class-methods Timespan::new(), Timespan::starting(), etcetera, instead.
  173. *
  174. * @return object Timespan
  175. * @access private
  176. * @since 5/2/05
  177. */
  178. function Timespan () {
  179. }
  180.  
  181. /**
  182. * Store the start DateAndTime of this timespan
  183. *
  184. * @param object DateAndTime $aDateAndTime
  185. * @return void
  186. * @access private
  187. * @since 5/4/05
  188. */
  189. function setStart ( $aDateAndTime ) {
  190. $this->start =$aDateAndTime;
  191. }
  192. /**
  193. * Set the Duration of this timespan
  194. *
  195. * @param object Duration $aDuration
  196. * @return void
  197. * @access private
  198. * @since 5/4/05
  199. */
  200. function setDuration ( $aDuration ) {
  201. $this->duration =$aDuration;
  202. }
  203.  
  204. /*******************************************************
  205. * Instance methods - Comparing/Testing
  206. *********************************************************/
  207.  
  208. /**
  209. * Test if this Timespan is equal to a Timespan.
  210. *
  211. * @param object Timespan $aTimespan
  212. * @return boolean
  213. * @access public
  214. * @since 5/3/05
  215. */
  216. function isEqualTo ( $aTimespan ) {
  217. return ($this->start->isEqualTo($aTimespan->start())
  218. && $this->duration->isEqualTo($aTimespan->duration()));
  219. }
  220. /**
  221. * Test if this Timespan is less than a comparand.
  222. *
  223. * @param object $aComparand
  224. * @return boolean
  225. * @access public
  226. * @since 5/3/05
  227. */
  228. function isLessThan ( $aComparand ) {
  229. return ($this->start->isLessThan($aComparand));
  230. }
  231. /**
  232. * Answer TRUE if the argument is within the timespan covered by the reciever.
  233. *
  234. * @param object DateAndTime $aDateAndTime A DateAndTime or Timespan.
  235. * @return boolean
  236. * @access public
  237. * @since 5/13/05
  238. */
  239. function includes ( $aDateAndTime ) {
  240. // If the argument is a Timespan, check the end-date as well.
  241. if (strtolower(get_class($aDateAndTime)) == 'timespan'
  242. || is_subclass_of($aDateAndTime, 'Timespan'))
  243. {
  244. return ($this->includes($aDateAndTime->start())
  245. && $this->includes($aDateAndTime->end()));
  246. }
  247. // If the argument is a DateAndTime, just check it.
  248. else {
  249. $asDandT =$aDateAndTime->asDateAndTime();
  250. return $asDandT->isBetween($this->start(), $this->end());
  251. }
  252. }
  253. /**
  254. * Answer whether all the elements of anArray are in the receiver.
  255. *
  256. * @param array $anArray An array of Timespans or DateAndTimes.
  257. * @return boolean
  258. * @access public
  259. * @since 5/13/05
  260. */
  261. function includesAllOf ( $anArray ) {
  262. foreach (array_keys($anArray) as $key) {
  263. if (!$this->includes($anArray[$key]))
  264. return FALSE;
  265. }
  266. return TRUE;
  267. }
  268. /**
  269. * Answer whether any the elements of anArray are in the receiver.
  270. *
  271. * @param array $anArray An array of Timespans or DateAndTimes.
  272. * @return boolean
  273. * @access public
  274. * @since 5/13/05
  275. */
  276. function includesAnyOf ( $anArray ) {
  277. foreach (array_keys($anArray) as $key) {
  278. if ($this->includes($anArray[$key]))
  279. return TRUE;
  280. }
  281. return FALSE;
  282. }
  283.  
  284. /*******************************************************
  285. * Instance methods - Operations
  286. *********************************************************/
  287.  
  288. /**
  289. * Return the Timespan both have in common, or null
  290. *
  291. * @param object Timespan $aTimespan
  292. * @return mixed object Timespan OR null
  293. * @access public
  294. * @since 5/13/05
  295. */
  296. function intersection ( $aTimespan ) {
  297. $start =$this->start();
  298. $end =$this->end();
  299. $aBeginning =$start->max($aTimespan->start());
  300. $anEnd =$end->min($aTimespan->end());
  301. if ($anEnd->isLessThan($aBeginning)) {
  302. $null = null;
  303. return $null;
  304. } else {
  305. eval('$result = '.get_class($this).'::startingEnding($aBeginning, $anEnd);');
  306. return $result;
  307. }
  308. }
  309. /**
  310. * Subtract a Duration or DateAndTime.
  311. *
  312. * @param object $operand
  313. * @return object Timespan (if operand is a Duration) OR Duration (if operand is a DateAndTime).
  314. * @access public
  315. * @since 5/3/05
  316. */
  317. function minus ( $operand ) {
  318. $methods = get_class_methods($operand);
  319. // If this conforms to the DateAndTimeProtocal
  320. if (in_array('asdateandtime', $methods)
  321. | in_array('asDateAndTime', $methods))
  322. {
  323. $obj =$this->start->minus($operand);
  324. return $obj;
  325. }
  326. // If this conforms to the Duration protocal
  327. else {
  328. $obj =$this->plus($operand->negated());
  329. return $obj;
  330. }
  331. }
  332.  
  333. /**
  334. * Answer the next object of our duration.
  335. *
  336. * @return object Timespan
  337. * @access public
  338. * @since 5/10/05
  339. */
  340. function next () {
  341. eval('$result = '.get_class($this).'::startingDuration(
  342. $this->start->plus($this->duration),
  343. $this->duration,
  344. "'.get_class($this).'");');
  345. return $result;
  346. }
  347. /**
  348. * Add a Duration.
  349. *
  350. * @param object Duration $aDuration
  351. * @return object Timespan The result.
  352. * @access public
  353. * @since 5/3/05
  354. */
  355. function plus ( $aDuration ) {
  356. $classname = get_class($this);
  357. eval('$result = '.$classname.'::startingDuration($this->start->plus($aDuration),
  358. $this->duration());');
  359. return $result;
  360. }
  361. /**
  362. * Answer the previous object of our duration.
  363. *
  364. * @return object Timespan
  365. * @access public
  366. * @since 5/10/05
  367. */
  368. function previous () {
  369. eval('$result = '.get_class($this).'::startingDuration(
  370. $this->start->minus($this->duration),
  371. $this->duration,
  372. "'.get_class($this).'");');
  373. return $result;
  374. }
  375. /**
  376. * Return the Timespan spanned by both
  377. *
  378. * @param object Timespan $aTimespan
  379. * @return mixed object Timespan OR null
  380. * @access public
  381. * @since 5/13/05
  382. */
  383. function union ( $aTimespan ) {
  384. $start =$this->start();
  385. $end =$this->end();
  386. $aBeginning =$start->min($aTimespan->start());
  387. $anEnd =$end->max($aTimespan->end());
  388. $obj = Timespan::startingEnding(
  389. $aBeginning,
  390. $anEnd->plus(DateAndTime::clockPrecision()));
  391. return $obj;
  392. }
  393. /*******************************************************
  394. * Instance Methods - Accessing
  395. *********************************************************/
  396.  
  397. /**
  398. * Answer the day
  399. *
  400. * @return integer
  401. * @access public
  402. * @since 5/13/05
  403. */
  404. function day () {
  405. return $this->dayOfYear();
  406. }
  407. /**
  408. * Answer the day of the month represented by the receiver.
  409. *
  410. * @return integer
  411. * @access public
  412. * @since 5/11/05
  413. */
  414. function dayOfMonth () {
  415. return $this->start->dayOfMonth();
  416. }
  417. /**
  418. * Answer the day of the week represented by the receiver.
  419. *
  420. * @return integer
  421. * @access public
  422. * @since 5/11/05
  423. */
  424. function dayOfWeek () {
  425. return $this->start->dayOfWeek();
  426. }
  427. /**
  428. * Answer the day of the week represented by the receiver.
  429. *
  430. * @return integer
  431. * @access public
  432. * @since 5/11/05
  433. */
  434. function dayOfWeekName () {
  435. return $this->start->dayOfWeekName();
  436. }
  437. /**
  438. * Answer the day of the year represented by the receiver.
  439. *
  440. * @return integer
  441. * @access public
  442. * @since 5/11/05
  443. */
  444. function dayOfYear () {
  445. return $this->start->dayOfYear();
  446. }
  447. /**
  448. * Answer the number of days in the month represented by the receiver.
  449. *
  450. * @return ingteger
  451. * @access public
  452. * @since 5/13/05
  453. */
  454. function daysInMonth () {
  455. return $this->start->daysInMonth();
  456. }
  457. /**
  458. * Answer the number of days in the year represented by the receiver.
  459. *
  460. * @return ingteger
  461. * @access public
  462. * @since 5/13/05
  463. */
  464. function daysInYear () {
  465. return $this->start->daysInYear();
  466. }
  467. /**
  468. * Answer the number of days in the year after the date of the receiver.
  469. *
  470. * @return ingteger
  471. * @access public
  472. * @since 5/13/05
  473. */
  474. function daysLeftInYear () {
  475. return $this->start->daysLeftInYear();
  476. }
  477.  
  478. /**
  479. * Answer the Duration of this timespan
  480. *
  481. * @return object Duration
  482. * @access public
  483. * @since 5/11/05
  484. */
  485. function duration () {
  486. return $this->duration;
  487. }
  488. /**
  489. * Answer the end of this timespan
  490. *
  491. * @return object DateAndTime
  492. * @access public
  493. * @since 5/11/05
  494. */
  495. function end () {
  496. $next =$this->next();
  497. $nextStart =$next->start();
  498. $obj =$nextStart->minus(DateAndTime::clockPrecision());
  499. return $obj;
  500. }
  501. /**
  502. * Answer the day-in-the-year of the first day of our month
  503. *
  504. * @return integer
  505. * @access public
  506. * @since 5/13/05
  507. */
  508. function firstDayOfMonth () {
  509. return $this->start->firstDayOfMonth();
  510. }
  511. /**
  512. * Answer TRUE if the year represented by the receiver is a leap year.
  513. *
  514. * @return integer
  515. * @access public
  516. * @since 5/11/05
  517. */
  518. function isLeapYear () {
  519. return $this->start->isLeapYear();
  520. }
  521. /**
  522. * Answer the Julian day number represented by the reciever.
  523. *
  524. * @return integer
  525. * @access public
  526. * @since 5/11/05
  527. */
  528. function julianDayNumber () {
  529. return $this->start->julianDayNumber();
  530. }
  531. /**
  532. * Return a printable string
  533. *
  534. * @return string
  535. * @access public
  536. * @since 5/13/05
  537. */
  538. function printableString () {
  539. return $this->start->printableString().'D'.$this->duration->printableString();
  540. }
  541. /**
  542. * Answer the month represented by the receiver.
  543. *
  544. * @return integer
  545. * @access public
  546. * @since 5/11/05
  547. */
  548. function startMonth () {
  549. return $this->start->month();
  550. }
  551. /**
  552. * Answer the month represented by the receiver.
  553. *
  554. * @return integer
  555. * @access public
  556. * @since 5/11/05
  557. */
  558. function startMonthAbbreviation () {
  559. return $this->start->monthAbbreviation();
  560. }
  561. /**
  562. * Answer the month represented by the receiver.
  563. *
  564. * @return integer
  565. * @access public
  566. * @since 5/11/05
  567. */
  568. function startMonthIndex () {
  569. return $this->start->monthIndex();
  570. }
  571. /**
  572. * Answer the month represented by the receiver.
  573. *
  574. * @return integer
  575. * @access public
  576. * @since 5/11/05
  577. */
  578. function startMonthName () {
  579. return $this->start->monthName();
  580. }
  581. /**
  582. * Answer the start DateAndTime of this timespan
  583. *
  584. * @return object DateAndTime
  585. * @access public
  586. * @since 5/11/05
  587. */
  588. function start () {
  589. return $this->start;
  590. }
  591. /**
  592. * Answer the year represented by the receiver.
  593. *
  594. * @return integer
  595. * @access public
  596. * @since 5/11/05
  597. */
  598. function startYear () {
  599. return $this->start->year();
  600. }
  601. /*******************************************************
  602. * Instance Methods - Enumerating
  603. *********************************************************/
  604.  
  605.  
  606. /**
  607. * Return an array of the DateAndTimes that occur every $aDuration in the reciever.
  608. *
  609. * @return array
  610. * @access public
  611. * @since 5/13/05
  612. */
  613. function every ( $aDuration ) {
  614. $every = array();
  615. $element =$this->start;
  616. $end =$this->end();
  617. while ($element->isLessThanOrEqualTo($end)) {
  618. $every[] =$element;
  619. $element =$element->plus($aDuration);
  620. }
  621. return $every;
  622. }
  623. /**
  624. * Return an array of the dates in the reciever.
  625. *
  626. * @return array
  627. * @access public
  628. * @since 5/13/05
  629. */
  630. function dates () {
  631. $dates = array();
  632. $element =$this->start->asDate();
  633. $end =$this->end();
  634. while ($element->isLessThanOrEqualTo($end)) {
  635. $dates[] =$element;
  636. $element =$element->next();
  637. }
  638. return $dates;
  639. }
  640. /**
  641. * Return an array of the Months in the reciever.
  642. *
  643. * @return array
  644. * @access public
  645. * @since 5/13/05
  646. */
  647. function months () {
  648. $months = array();
  649. $element =$this->start->asMonth();
  650. $end =$this->end();
  651. while ($element->isLessThanOrEqualTo($end)) {
  652. $months[] =$element;
  653. $element =$element->next();
  654. }
  655. return $months;
  656. }
  657. /**
  658. * Return an array of the weeks in the reciever.
  659. *
  660. * @return array
  661. * @access public
  662. * @since 5/13/05
  663. */
  664. function weeks () {
  665. $weeks = array();
  666. $element =$this->start->asWeek();
  667. $end =$this->end();
  668. while ($element->isLessThanOrEqualTo($end)) {
  669. $weeks[] =$element;
  670. $element =$element->next();
  671. }
  672. return $weeks;
  673. }
  674. /**
  675. * Return an array of the years in the reciever.
  676. *
  677. * @return array
  678. * @access public
  679. * @since 5/13/05
  680. */
  681. function years () {
  682. $years = array();
  683. $element =$this->start->asYear();
  684. $end =$this->end();
  685. while ($element->isLessThanOrEqualTo($end)) {
  686. $years[] =$element;
  687. $element =$element->next();
  688. }
  689. return $years;
  690. }
  691. /*******************************************************
  692. * Instance Methods - Converting
  693. *********************************************************/
  694.  
  695. /**
  696. * Answer this instance converted.
  697. *
  698. * @return obect Date
  699. * @access public
  700. * @since 5/13/05
  701. */
  702. function asDate () {
  703. $obj =$this->start->asDate();
  704. return $obj;
  705. }
  706. /**
  707. * Answer this instance converted.
  708. *
  709. * @return obect DateAndTime
  710. * @access public
  711. * @since 5/13/05
  712. */
  713. function asDateAndTime () {
  714. return $this->start;
  715. }
  716. /**
  717. * Answer this instance converted.
  718. *
  719. * @return obect Duration
  720. * @access public
  721. * @since 5/13/05
  722. */
  723. function asDuration () {
  724. return $this->duration;
  725. }
  726. /**
  727. * Answer this instance converted.
  728. *
  729. * @return obect Month
  730. * @access public
  731. * @since 5/13/05
  732. */
  733. function asMonth () {
  734. $obj =$this->start->asMonth();
  735. return $obj;
  736. }
  737. /**
  738. * Answer this instance converted.
  739. *
  740. * @return obect Time
  741. * @access public
  742. * @since 5/13/05
  743. */
  744. function asTime () {
  745. $obj =$this->start->asTime();
  746. return $obj;
  747. }
  748. /**
  749. * Answer this instance converted.
  750. *
  751. * @return obect TimeStamp
  752. * @access public
  753. * @since 5/13/05
  754. */
  755. function asTimeStamp () {
  756. $obj =$this->start->asTimeStamp();
  757. return $obj;
  758. }
  759. /**
  760. * Answer this instance converted.
  761. *
  762. * @return obect Week
  763. * @access public
  764. * @since 5/13/05
  765. */
  766. function asWeek () {
  767. $obj =$this->start->asWeek();
  768. return $obj;
  769. }
  770. /**
  771. * Answer this instance converted.
  772. *
  773. * @return obect Year
  774. * @access public
  775. * @since 5/13/05
  776. */
  777. function asYear () {
  778. $obj =$this->start->asYear();
  779. return $obj;
  780. }
  781. /**
  782. * Answer an Timespan. anEnd must be aDateAndTime or a Timespan
  783. *
  784. * @param object $anEnd Must be a DateAndTime or a Timespan
  785. * @return object Timespan
  786. * @access public
  787. * @since 5/13/05
  788. */
  789. function to ( $anEnd ) {
  790. $obj = Timespan::startingEnding($this->start(), $anEnd->asDateAndTime());
  791. return $obj;
  792. }
  793. }
  794.  
  795. require_once(dirname(__FILE__)."/DateAndTime.class.php");
  796.  
  797. ?>

Documentation generated on Wed, 19 Sep 2007 10:27:26 -0400 by phpDocumentor 1.3.0RC3