Overview

Namespaces

  • Apptus
    • ESales
      • Connector
        • Report
        • Time
    • Util
      • Cache
  • PHP
  • Overview
  • Namespace
  • Class
  • Tree
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 
<?php
namespace Apptus\ESales\Connector\Time;

/**
 * An interval between two points in time.
 *
 * The interval may be expressed as either a start and an end time, or as
 * one of those and a duration.
 *
 * This class represents the ISO 8601 time interval concept, which allows
 * the different formats to express a time interval:
 *
 * <il>
 * <li>&lt;start&gt;/&lt;duration&gt;
 * <li>&lt;start&gt;/&lt;end&gt;
 * <li>&lt;duration&gt;/&lt;end&gt;
 * </il>
 * where start and end is specified using ISO 8601 date and time, while
 * a duration is specified using a ISO 8601 duration.
 */
class TimeInterval {
    /**
     * Convenience method for returning a time interval covering a complete
     * calendar year. The start date is expressed in local time.
     *
     * @param int
     *          The year.
     * @return TimeInterval A time interval with duration 1 year, starting at <i>year</i>-01-01.
     */
    public static function year($year) {
        return self::create(new IsoDateTime(new CalendarDate($year, 1, 1), null),
                Duration::create(1, Unit::YEAR));
    }

    /**
     * Convenience method for returning a time interval covering a complete
     * calendar quarter. The start date is expressed in local time.
     *
     * @param int
     *          The year.
     * @param int
     *          The quarter.
     * @return TimeInterval A time interval with duration 3 months, starting at the
     * first month of the quarter.
     */
    public static function quarter($year, $quarter) {
        $month = Month::forStartOfQuarter($quarter);
        return self::create(new IsoDateTime(new CalendarDate($year, $month, 1), null),
                Duration::create(3, Unit::MONTH));
    }

    /**
     * Convenience method for returning a time interval covering a complete
     * calendar month. The start date is expressed in local time.
     *
     * @param int
     *          The year.
     * @param int
     *          The month.
     * @return TimeInterval A time interval with duration 1 month, starting at the
     * first day of the month.
     */
    public static function month($year, $month) {
        $month = Month::validate($month);
        return self::create(new IsoDateTime(new CalendarDate($year, $month, 1), null),
                Duration::create(1, Unit::MONTH));
    }

    /**
     * Convenience method for returning a time interval covering a complete
     * calendar week according to the ISO 8601 week rules. The start date is
     * expressed in local time.
     *
     * @param int
     *          The year.
     * @param int
     *          The week.
     * @return TimeInterval A time interval with duration 1 week, starting at the
     * first day of the week.
     */
    public static function week($year, $week) {
        $tz = new \DateTimeZone('UTC');
        $dt = new \DateTime($year . 'W' . $week, $tz);
        $date = TimePoint::fromDateTime($dt)->date($tz);
        return self::create(new IsoDateTime($date, null), Duration::create(1, Unit::WEEK));
    }

    /**
     * Convenience method for returning a time interval covering a complete
     * calendar day.
     *
     * @param int
     *          The year.
     * @param int
     *          The month.
     * @param int
     *          The day.
     * @return TimeInterval A time interval with duration 1 day, starting at
     * 00:00:00 on the specified day.
     */
    public static function day($year, $month, $day) {
        $month = Month::validate($month);
        return self::create(new IsoDateTime(new CalendarDate($year, $month, $day),
                new Time(0, 0, 0, null)),
                Duration::create(1, Unit::DAY));
    }

    /**
     * Convenience method for returning a time interval covering today.
     * The start date is expressed in local time.
     *
     * @param \DateTimeZone Time zone to decide which day is "today".
     * @return TimeInterval A time interval with duration 1 day, starting at
     * 00:00:00 today.
     */
    public static function today(\DateTimeZone $tz) {
        return self::create(TimePoint::today($tz)->dateTime($tz),
                Duration::create(1, Unit::DAY));
    }

    /**
     * Create a TimeInterval between two IsoDateTime instances or from an IsoDateTime and a Duration.
     *
     * At least one of the arguments must be an IsoDateTime.
     *
     * @param IsoDateTime|Duration Start point or duration of the interval.
     * @param IsoDateTime|Duration End point or duration of the interval.
     * @throws \InvalidArgumentException
     * @return TimeInterval
     */
    public static function create($start, $end) {
        if ($start instanceof IsoDateTime) {
            if ($end instanceof IsoDateTime) {
                return new TimeInterval($start, null, $end);
            } elseif ($end instanceof Duration) {
                return new TimeInterval($start, $end, null);
            } else {
                $type = gettype($end) === 'object' ? get_class($end) : gettype($end);
                throw new \InvalidArgumentException('Invalid end. Expected IsoDateTime or Duration, got ' . $type);
            }
        } elseif ($start instanceof Duration) {
            if ($end instanceof IsoDateTime) {
                return new TimeInterval(null, $start, $end);
            } elseif ($end instanceof Duration) {
                throw new \InvalidArgumentException('Expected a starting or ending IsoDateTime, got two Duration instances.');
            } else {
                $type = gettype($end) === 'object' ? get_class($end) : gettype($end);
                throw new \InvalidArgumentException('Invalid end. Expected IsoDateTime or Duration, got ' . $type);
            }
        } else {
            $type = gettype($start) === 'object' ? get_class($start) : gettype($start);
            throw new \InvalidArgumentException('Invalid start. Expected IsoDateTime or Duration, got ' . $type);
        }
    }

    /**
     * Parses a time interval on any of the three valid formats.
     *
     * @param string
     *          The input string.
     * @throws \InvalidArgumentException if the input cannot be parsed.
     * @return TimeInterval A time interval.
     */
    public static function parse($iso) {
        $ix = strpos($iso, '/');

        if ($ix === false || $ix !== strrpos($iso, '/')) {
            throw new \InvalidArgumentException('Illegal format. Wrong number of \'/\' for a range.');
        }

        $firstPart = substr($iso, 0, $ix);
        $lastPart = substr($iso, $ix + 1);

        $start = null;
        $end = null;
        $duration = null;

        if ($firstPart[0] === 'P') {
            $duration = Duration::parse($firstPart);
            $end = IsoDateTime::parse($lastPart);
        } elseif ($lastPart[0] === 'P') {
            $start = IsoDateTime::parse($firstPart);
            $duration = Duration::parse($lastPart);
        } else {
            $start = IsoDateTime::parse($firstPart);
            $end = IsoDateTime::parseInContext($lastPart, $start);
        }

        return new TimeInterval($start, $duration, $end);
    }

    private $start;
    private $end;
    private $duration;

    private function __construct(IsoDateTime $start = null, Duration $duration = null, IsoDateTime $end = null) {
        $this->start = $start;
        $this->end = $end;
        $this->duration = $duration;
    }

    /**
     * Returns the start point in time, given the time zone for local time.
     *
     * @param \DateTimeZone The local time zone.
     * @return TimePoint The start point in time.
     */
    public function start(\DateTimeZone $tz) {
        if ($this->start !== null) {
            return $this->start->toTimePoint($tz);
        }

        return $this->end->toTimePoint($tz)->back($this->duration, $tz);
    }

    /**
     * Returns the end point in time, given the time zone for local time.
     *
     * @param \DateTimeZone The local time zone.
     * @return TimePoint The end point in time.
     */
    public function end(\DateTimeZone $tz) {
        if ($this->end !== null) {
            return $this->end->toTimePoint($tz);
        }

        return $this->start->toTimePoint($tz)->forward($this->duration, $tz);
    }

    /**
     * Returns the duration of this time interval, given the time zone for local time.
     *
     * If this interval was specified by start and end times, the duration is
     * calculated using the given time zone.
     *
     * Note that if the duration is calculated, it will be specified in hours,
     * minutes and seconds only. The number of hours may be very large for long
     * intervals.
     *
     * @param \DateTimeZone The local time zone.
     * @return Duration The length of this time interval.
     */
    public function duration(\DateTimeZone $tz) {
        if ($this->duration !== null) {
            return $this->duration;
        }
        $s = $this->start($tz)->toTimestamp();
        $e = $this->end($tz)->toTimestamp();
        $seconds = $e - $s;
        if (gettype($seconds) === 'double') {
            $seconds = (int) round($seconds);
        }
        if ($seconds === 0) {
            return Duration::create(0, Unit::SECOND);
        }
        $minutes = (int) ($seconds / 60);
        $seconds %= 60;
        $hours = (int) ($minutes / 60);
        $minutes %= 60;
        $elements = array ();
        if ($hours > 0) $elements[Unit::HOUR] = $hours;
        if ($minutes > 0) $elements[Unit::MINUTE] = $minutes;
        if ($seconds > 0) $elements[Unit::SECOND] = $seconds;
        return new Duration($elements);
    }

    /**
     * True if the argument is a time interval specified by the very same
     * components as this time interval.
     *
     * Two time intervals may cover the same
     * set of time points in all time zones and for all locales and still not be
     * considered equal, depending on how they are specified.
     *
     * @param mixed
     * @return boolean
     */
    public function equals($o) {
        if ($o instanceof TimeInterval) {
            $that = $o;

            if ($this->start !== null && $this->end !== null) {
                return $this->start->equals($that->start) && $this->end->equals($that->end);
            } else if ($this->start !== null && $this->duration !== null) {
                return $this->start->equals($that->start) && $this->duration->equals($that->duration);
            } else if ($this->duration !== null && $this->end !== null) {
                return $this->duration->equals($that->duration) && $this->end->equals($that->end);
            }
        }

        return false;
    }

    /**
     * Returns an ISO 8601 formatted string representing this time interval.
     *
     * @return string
     */
    public function __toString() {
        $result = '';

        if ($this->start !== null && $this->end !== null) {
            $result .= $this->start . '/' . $this->end;
        } elseif ($this->start !== null && $this->duration !== null) {
            $result .= $this->start . '/' . $this->duration;
        } elseif ($this->duration !== null && $this->end !== null) {
            $result .= $this->duration . '/' . $this->end;
        } else {
            $result .= $this->duration;
        }

        return $result;
    }

    /**
     * Returns the length in seconds for this time interval,
     * given a local time zone.
     *
     * @param \DateTimeZone The local time zone.
     * @return float|int The length in seconds of this interval.
     */
    public function toSeconds(\DateTimeZone $tz) {
        return $this->end($tz)->toTimestamp() - $this->start($tz)->toTimestamp();
    }
}
Apptus ESales Connector PHP API documentation generated by ApiGen