start moving repeaters to Horde_Date_Repeater
authorChuck Hagenbuch <chuck@horde.org>
Tue, 3 Feb 2009 17:34:00 +0000 (12:34 -0500)
committerChuck Hagenbuch <chuck@horde.org>
Tue, 3 Feb 2009 22:33:37 +0000 (17:33 -0500)
30 files changed:
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Day.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/DayName.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/DayPortion.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Hour.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Minute.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Month.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/MonthName.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Season.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/SeasonName.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Second.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Time.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Week.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Weekend.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Year.php [deleted file]
framework/Date_Parser/lib/Horde/Date/Repeater.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Day.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/DayName.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/DayPortion.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Exception.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Hour.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Minute.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Month.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/MonthName.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Season.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/SeasonName.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Second.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Time.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Week.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Weekend.php [new file with mode: 0644]
framework/Date_Parser/lib/Horde/Date/Repeater/Year.php [new file with mode: 0644]

diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Day.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Day.php
deleted file mode 100644 (file)
index 98a3bc5..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Day extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    // (24 * 60 * 60)
-    const DAY_SECONDS = 86400;
-
-    public $currentDayStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        if (!$this->currentDayStart) {
-            $this->currentDayStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
-        }
-
-        $direction = ($pointer == 'future') ? 1 : -1;
-        $this->currentDayStart->day += $direction;
-
-        $end = clone($this->currentDayStart);
-        $end->day += 1;
-
-        return new Horde_Date_Span($this->currentDayStart, $end);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'future':
-            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour + 1));
-            $dayEnd = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day + 1));
-            break;
-
-        case 'past':
-            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day));
-            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour));
-            break;
-
-        case 'none':
-            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day));
-            $dayEnd = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day + 1));
-            break;
-        }
-
-        return new Horde_Date_Span($dayBegin, $dayEnd);
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-        return $span->add(array('day' => $direction * $amount));
-    }
-
-    public function width()
-    {
-        return self::DAY_SECONDS;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-day';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/DayName.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/DayName.php
deleted file mode 100644 (file)
index 9ad6291..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_DayName extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    // (24 * 60 * 60)
-    const DAY_SECONDS = 86400;
-
-    public $currentDayStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        $direction = ($pointer == 'future') ? 1 : -1;
-
-        if (!$this->currentDayStart) {
-            $this->currentDayStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + $direction));
-
-            $dayNum = $this->type;
-            while ($this->currentDayStart->dayOfWeek() != $dayNum) {
-                $this->currentDayStart->day += $direction;
-            }
-        } else {
-            $this->currentDayStart->day += $direction * 7;
-        }
-
-        $end = clone($this->currentDayStart);
-        $end->day++;
-        return new Horde_Date_Span($this->currentDayStart, $end);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::next($pointer);
-
-        if ($pointer == 'none') {
-            $pointer = 'future';
-        }
-        return $this->next($pointer);
-    }
-
-    public function width()
-    {
-        return self::DAY_SECONDS;
-    }
-
-    public function __toString()
-    {
-        $dayStrings = array(
-            Horde_Date::DATE_MONDAY => 'monday',
-            Horde_Date::DATE_TUESDAY => 'tuesday',
-            Horde_Date::DATE_WEDNESDAY => 'wednesday',
-            Horde_Date::DATE_THURSDAY => 'thursday',
-            Horde_Date::DATE_FRIDAY => 'friday',
-            Horde_Date::DATE_SATURDAY => 'saturday',
-            Horde_Date::DATE_SUNDAY => 'sunday',
-        );
-        return parent::__toString() . '-dayname-' . $dayStrings[$this->type];
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/DayPortion.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/DayPortion.php
deleted file mode 100644 (file)
index 153db39..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_DayPortion extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    /**
-     * 6am-12am (6 * 60 * 60, 12 * 60 * 60)
-     */
-    public static $morning = array(21600, 43200);
-
-    /**
-     * 1pm-5pm (13 * 60 * 60, 17 * 60 * 60)
-     */
-    public static $afternoon = array(46800, 61200);
-
-    /**
-     * 5pm-8pm (17 * 60 * 60, 20 * 60 * 60)
-     */
-    public static $evening = array(61200, 72000);
-
-    /**
-     * 8pm-12pm (20 * 60 * 60, 24 * 60 * 60)
-     */
-    public static $night = array(72000, 86400);
-
-    public $range;
-    public $currentSpan;
-
-    public function __construct($type)
-    {
-        parent::__construct($type);
-
-        if (is_int($type)) {
-            $this->range = array(($type * 3600), (($type + 12) * 3600));
-        } else {
-            $lookup = array(
-                'am' => array(0, (12 * 3600 - 1)),
-                'pm' => array((12 * 3600), (24 * 3600 - 1)),
-                'morning' => self::$morning,
-                'afternoon' => self::$afternoon,
-                'evening' => self::$evening,
-                'night' => self::$night,
-            );
-            if (!isset($lookup[$type])) {
-                throw new InvalidArgumentException("Invalid type '$type' for Repeater_DayPortion");
-            }
-            $this->range = $lookup[$type];
-        }
-    }
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        $fullDay = 60 * 60 * 24;
-
-        if (!$this->currentSpan) {
-            $nowSeconds = $this->now->hour * 3600 + $this->now->min * 60 + $this->now->sec;
-            if ($nowSeconds < $this->range[0]) {
-                switch ($pointer) {
-                case 'future':
-                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day, 'sec' => $this->range[0]));
-                    break;
-
-                case 'past':
-                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day - 1, 'sec' => $this->range[0]));
-                    break;
-                }
-            } elseif ($nowSeconds > $this->range[1]) {
-                switch ($pointer) {
-                case 'future':
-                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1, 'sec' => $this->range[0]));
-                    break;
-
-                case 'past':
-                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day, 'sec' => $this->range[0]));
-                    break;
-                }
-            } else {
-                switch ($pointer) {
-                case 'future':
-                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1, 'sec' => $this->range[0]));
-                    break;
-
-                case 'past':
-                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day - 1, 'sec' => $this->range[0]));
-                    break;
-                }
-            }
-
-            $rangeEnd = new Horde_Date(array('year' => $rangeStart->year, 'month' => $rangeStart->month, 'day' => $rangeStart->day, 'sec' => $this->range[1] - $this->range[0]));
-            $this->currentSpan = new Horde_Date_Span($rangeStart, $rangeEnd);
-        } else {
-            switch ($pointer) {
-            case 'future':
-                $this->currentSpan = $this->currentSpan->add(array('day' => 1));
-                break;
-
-            case 'past':
-                $this->currentSpan = $this->currentSpan->add(array('day' => -1));
-                break;
-            }
-        }
-
-        return $this->currentSpan;
-    }
-
-    public function this($context = 'future')
-    {
-        parent::super($context);
-
-        $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day, 'sec' => $this->range[0]));
-        $rangeEnd = new Horde_Date(array('year' => $rangeStart->year, 'month' => $rangeStart->month, 'day' => $rangeStart->day, 'sec' => $this->range[1] - $this->range[0]));
-        $this->currentSpan = new Horde_Date_Span($rangeStart, $rangeEnd);
-        return $this->currentSpan;
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $this->now = $span->begin;
-        $portionSpan = $this->next($pointer);
-        $direction = ($pointer == 'future') ? 1 : -1;
-        return $portionSpan + ($direction * ($amount - 1) * Horde_Date_Parser_Locale_Base_Repeater_Day::DAY_SECONDS);
-    }
-
-    public function width()
-    {
-        if (!$this->range) {
-            throw new Horde_Date_Parser_Exception('Range has not been set');
-        }
-
-        if ($this->currentSpan) {
-            return $this->currentSpan->width();
-        }
-
-        if (is_int($this->type)) {
-            return (12 * 3600);
-        } else {
-            return $this->range[1] - $this->range[0];
-        }
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-dayportion-' . $this->type;
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Hour.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Hour.php
deleted file mode 100644 (file)
index 598c004..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Hour extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    public $currentHourStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        $direction = ($pointer == 'future') ? 1 : -1;
-        if (!$this->currentHourStart) {
-            $this->currentHourStart = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour));
-        }
-        $this->currentHourStart->hour += $direction;
-
-        $end = clone($this->currentHourStart);
-        $end->hour++;
-        return new Horde_Date_Span($this->currentHourStart, $end);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'future':
-            $hourStart = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min + 1));
-            $hourEnd = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour + 1));
-            break;
-
-        case 'past':
-            $hourStart = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour));
-            $hourEnd = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour + 1, 'min' => $this->now->min));
-            break;
-
-        case 'none':
-            $hourStart = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour));
-            $hourEnd = clone($hourStart);
-            $hourEnd->hour++;
-            break;
-        }
-
-        return new Horde_Date_Span($hourStart, $hourEnd);
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-        return $span->add(array('hour' => $direction * $amount));
-    }
-
-    public function width()
-    {
-        return 3600;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-hour';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Minute.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Minute.php
deleted file mode 100644 (file)
index 679cdf9..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Minute extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    public $currentMinuteStart;
-
-    public function next($pointer = 'future')
-    {
-        parent::next($pointer);
-
-        if (!$this->currentMinuteStart) {
-            $this->currentMinuteStart = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
-        }
-        $direction = ($pointer == 'future') ? 1 : -1;
-        $this->currentMinuteStart->min += $direction;
-
-        $end = clone($this->currentMinuteStart);
-        $end->min++;
-        return new Horde_Date_Span($this->currentMinuteStart, $end);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'future':
-            $minuteBegin = clone($this->now);
-            $minuteEnd = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
-            break;
-
-        case 'past':
-            $minuteBegin = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
-            $minuteEnd = clone($this->now);
-            break;
-
-        case 'none':
-            $minuteBegin = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
-            $minuteEnd = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min + 1));
-            break;
-        }
-
-        return new Horde_Date_Span($minuteBegin, $minuteEnd);
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-        return $span->add(array('min' => $diretion * $amount));
-    }
-
-    public function width()
-    {
-        return 60;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-minute';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Month.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Month.php
deleted file mode 100644 (file)
index 6e6ca92..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Month extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    /**
-     * 30 * 24 * 60 * 60
-     */
-    const MONTH_SECONDS = 2592000;
-
-    public $currentMonthStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        if (!$this->currentMonthStart) {
-            $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month));
-        }
-        $direction = ($pointer == 'future') ? 1 : -1;
-        $this->currentMonthStart->month += $direction;
-
-        $end = clone($this->currentMonthStart);
-        $end->month++;
-        return new Horde_Date_Span($this->currentMonthStart, $end);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'future':
-            $monthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1));
-            $monthEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month + 1));
-            break;
-
-        case 'past':
-            $monthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month));
-            $monthEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
-            break;
-
-        case 'none':
-            $monthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month));
-            $monthEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month + 1));
-            break;
-        }
-
-        return new Horde_Date_Span($monthStart, $monthEnd);
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-        return $span->add(array('month' => $amount * $direction));
-    }
-
-    public function width()
-    {
-        return self::MONTH_SECONDS;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-month';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/MonthName.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/MonthName.php
deleted file mode 100644 (file)
index 939f51d..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_MonthName extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    /**
-     * 30 * 24 * 60 * 60
-     */
-    const MONTH_SECONDS = 2592000;
-
-    public $currentMonthStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        if (!$this->currentMonthStart) {
-            $targetMonth = $this->_monthNumber($this->type);
-            switch ($pointer) {
-            case 'future':
-                if ($this->now->month > $targetMonth) {
-                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $targetMonth));
-                } else {
-                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year + 1, 'month' => $targetMonth));
-                }
-                break;
-
-            case 'none':
-                if ($this->now->month <= $targetMonth) {
-                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $targetMonth));
-                } else {
-                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year + 1, 'month' => $targetMonth));
-                }
-                break;
-
-            case 'past':
-                if ($this->now->month > $targetMonth) {
-                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $targetMonth));
-                } else {
-                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year - 1, 'month' => $targetMonth));
-                }
-                break;
-            }
-        } else {
-            switch ($pointer) {
-            case 'future':
-                $this->currentMonthStart->year++;
-                break;
-
-            case 'past':
-                $this->currentMonthStart->year--;
-                break;
-            }
-        }
-
-        return new Horde_Date_Span($this->currentMonthStart, new Horde_Date(array('year' => $this->currentMonthStart->year, 'month' => $this->currentMonthStart->month + 1)));
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'past':
-            return $this->next($pointer);
-
-        case 'future':
-        case 'none':
-            return $this->next('none');
-        }
-    }
-
-    public function width()
-    {
-        return self::MONTH_SECONDS;
-    }
-
-    public function index()
-    {
-        return $this->_monthNumber($this->type);
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-monthname-' . $this->type;
-    }
-
-    protected function _monthNumber($monthName)
-    {
-        $months = array(
-            'january' => 1,
-            'february' => 2,
-            'march' => 3,
-            'april' => 4,
-            'may' => 5,
-            'june' => 6,
-            'july' => 7,
-            'august' => 8,
-            'september' => 9,
-            'october' => 10,
-            'november' => 11,
-            'december' => 12,
-        );
-        if (!isset($months[$monthName])) {
-            throw new InvalidArgumentException('Invalid month name "' . $monthName . '"');
-        }
-        return $months[$monthName];
-    }
-
-}
\ No newline at end of file
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Season.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Season.php
deleted file mode 100644 (file)
index 1c57d1c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Season extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    /**
-     * 91 * 24 * 60 * 60
-     */
-    const SEASON_SECONDS = 7862400;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-        throw new Horde_Date_Parser_Exception('Not implemented');
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-        throw new Horde_Date_Parser_Exception('Not implemented');
-    }
-
-    public function width()
-    {
-        return self::SEASON_SECONDS;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-season';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/SeasonName.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/SeasonName.php
deleted file mode 100644 (file)
index 210332c..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_SeasonName extends Horde_Date_Parser_Locale_Base_Repeater_Season
-{
-    /**
-     * 91 * 24 * 60 * 60
-     */
-    const SEASON_SECONDS = 7862400;
-
-    public $summer = array('jul 21', 'sep 22');
-    public $autumn = array('sep 23', 'dec 21');
-    public $winter = array('dec 22', 'mar 19');
-    public $spring = array('mar 20', 'jul 20');
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-        throw new Horde_Date_Parser_Exception('Not implemented');
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-        throw new Horde_Date_Parser_Exception('Not implemented');
-    }
-
-    public function width()
-    {
-        return self::SEASON_SECONDS;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-season-' . $this->type;
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Second.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Second.php
deleted file mode 100644 (file)
index a26bfe4..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Second extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    public $secondStart;
-
-    public function next($pointer = 'future')
-    {
-        parent::next($pointer);
-
-        $direction = ($pointer == 'future') ? 1 : -1;
-
-        if (!$this->secondStart) {
-            $this->secondStart = clone($this->now);
-            $this->secondStart->sec += $direction;
-        } else {
-            $this->secondStart += $direction;
-        }
-
-        $end = clone($this->secondStart);
-        $end->sec++;
-        return new Horde_Date_Span($this->secondStart, $end);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        $end = clone($this->now);
-        $end->sec++;
-        return new Horde_Date_Span($this->now, $end);
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-        return $span->add($direction * $amount);
-    }
-
-    public function width()
-    {
-        return 1;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-second';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Time.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Time.php
deleted file mode 100644 (file)
index 0c9de67..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Time extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    public $currentTime;
-
-    public function __construct($time, $options = array())
-    {
-        $t = str_replace(':', '', $time);
-
-        switch (strlen($t)) {
-        case 1:
-        case 2:
-            $hours = (int)$t;
-            $this->type = ($hours == 12) ?
-                new Horde_Date_Tick(0, true) :
-                new Horde_Date_Tick($hours * 3600, true);
-            break;
-
-        case 3:
-            $this->type = new Horde_Date_Tick($t[0] * 3600 + (int)substr($t, 1, 2) * 60, true);
-            break;
-
-        case 4:
-            $ambiguous = (strpos($time, ':') !== false) && ($t[0] != 0) && ((int)substr($t, 0, 2) <= 12);
-            $hours = (int)substr($t, 0, 2);
-            $this->type = ($hours == 12) ?
-                new Horde_Date_Tick((int)substr($t, 2, 2) * 60, $ambiguous) :
-                new Horde_Date_Tick($hours * 60 * 60 + (int)substr($t, 2, 2) * 60, $ambiguous);
-            break;
-
-        case 5:
-            $this->type = new Horde_Date_Tick($t[0] * 3600 + (int)substr($t, 1, 2) * 60 + (int)substr($t, 3, 2), true);
-            break;
-
-        case 6:
-            $ambiguous = (strpos($time, ':') !== false) && ($t[0] != 0) && ((int)substr($t, 0, 2) <= 12);
-            $hours = (int)substr($t, 0, 2);
-            $this->type = ($hours == 12) ?
-                new Horde_Date_Tick((int)substr($t, 2, 2) * 60 + (int)substr($t, 4, 2), $ambiguous) :
-                new Horde_Date_Tick($hours * 60 * 60 + (int)substr($t, 2, 2) * 60 + (int)substr($t, 4, 2), $ambiguous);
-            break;
-
-        default:
-            throw new Horde_Date_Parser_Exception('Time cannot exceed six digits');
-        }
-    }
-
-    /**
-     * Return the next past or future Span for the time that this Repeater represents
-     *   pointer - Symbol representing which temporal direction to fetch the next day
-     *             must be either :past or :future
-     */
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        $halfDay = 3600 * 12;
-        $fullDay = 3600 * 24;
-
-        $first = false;
-
-        if (!$this->currentTime) {
-            $first = true;
-            $midnight = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
-            $yesterdayMidnight = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day - 1));
-            $tomorrowMidnight = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1));
-
-            if ($pointer == 'future') {
-                if ($this->type->ambiguous) {
-                    foreach (array($midnight + $this->type, $midnight + $halfDay + $this->type, $tomorrowMidnight + $this->type) as $t) {
-                        if ($t >= $this->now) {
-                            $this->currentTime = $t;
-                            break;
-                        }
-                    }
-                } else {
-                    foreach (array($midnight + $this->type, $tomorrowMidnight + $this->type) as $t) {
-                        if ($t >= $this->now) {
-                            $this->currentTime = $t;
-                            break;
-                        }
-                    }
-                }
-            } else {
-                if ($this->type->ambiguous) {
-                    foreach (array($midnight + $halfDay + $this->type, $midnight + $this->type, $yesterdayMidnight + $this->type * 2) as $t) {
-                        if ($t <= $this->now) {
-                            $this->currentTime = $t;
-                            break;
-                        }
-                    }
-                } else {
-                    foreach (array($midnight + $this->type, $yesterdayMidnight + $this->type) as $t) {
-                        if ($t <= $this->now) {
-                            $this->currentTime = $t;
-                            break;
-                        }
-                    }
-                }
-            }
-
-            if (!$this->currentTime) {
-                throw new Horde_Date_Parser_Exception('Current time cannot be null at this point');
-            }
-        }
-
-        if (!$first) {
-            $increment = $this->type->ambiguous ? $halfday : $fullDay;
-            $this->currentTime += ($pointer == 'future') ? $increment : -$increment;
-        }
-
-        return new Horde_Date_Span($this->currentTime, $this->currentTime + $this->width());
-    }
-
-    public function this($context = 'future')
-    {
-        parent::this($context);
-
-        if ($context == 'none') { $context = 'future'; }
-        return $this->next($context);
-    }
-
-    public function width()
-    {
-        return 1;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-time-' . $this->type;
-    }
-
-}
-
-class Horde_Date_Tick
-{
-    public $time;
-    public $ambiguous;
-
-    public function __construct($time, $ambiguous = false)
-    {
-        $this->time = $time;
-        $this->ambiguous = $ambiguous;
-    }
-
-    public function mult($other)
-    {
-        return new Horde_Date_Tick($this->time * $other, $this->ambiguous);
-    }
-
-    /*
-    def to_f
-      @time.to_f
-    end
-    */
-
-    public function __toString()
-    {
-        return $this->time . ($this->ambiguous ? '?' : '');
-    }
-
-}
\ No newline at end of file
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Week.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Week.php
deleted file mode 100644 (file)
index 92f2b6c..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Week extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    /**
-     * (7 * 24 * 60 * 60)
-     */
-    const WEEK_SECONDS = 604800;
-
-    public $currentWeekStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        if (!$this->currentWeekStart) {
-            switch ($pointer) {
-            case 'future':
-                $sundayRepeater = new Horde_Date_Parser_Locale_Base_Repeater_DayName(Horde_Date::DATE_SUNDAY);
-                $sundayRepeater->start = $this->now;
-                $nextSundaySpan = $sundayRepeater->next('future');
-                $this->currentWeekStart = $nextSundaySpan->begin;
-                break;
-
-            case 'past':
-                $sundayRepeater = new Horde_Date_Parser_Locale_Base_Repeater_DayName(Horde_Date::DATE_SUNDAY);
-                $sundayRepeater->start = clone($this->now);
-                $sundayRepeater->start->day++;
-                $sundayRepeater->next('past');
-                $lastSundaySpan = $sundayRepeater->next('past');
-                $currentWeekStart = $lastSundaySpan->begin;
-                break;
-            }
-        } else {
-            $direction = ($pointer == 'future') ? 1 : -1;
-            $this->currentWeekStart->day += $direction * 7;
-        }
-
-        $end = clone($this->currentWeekStart);
-        $end->day += 7;
-        return new Horde_Date_Span($this->currentWeekStart, $end);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'future':
-            $thisWeekStart = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour + 1));
-            $sundayRepeater = new Horde_Date_Parser_Locale_Base_Repeater_DayName(Horde_Date::DATE_SUNDAY);
-            $sundayRepeater->start = $this->now;
-            $thisSundaySpan = $sundayRepeater->this('future');
-            $thisWeekEnd = $thisSundaySpan->begin;
-            return new Horde_Date_Span($thisWeekStart, $thisWeekEnd);
-
-        case 'past':
-            $thisWeekEnd = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour));
-            $sundayRepeater = new Horde_Date_Parser_Locale_Base_Repeater_DayName(Horde_Date::DATE_SUNDAY);
-            $sundayRepeater->start = $this->now;
-            $lastSundaySpan = $sundayRepeater->next('past');
-            $thisWeekStart = $lastSundaySpan->begin;
-            return new Horde_Date_Span($thisWeekStart, $thisWeekEnd);
-
-        case 'none':
-            $sundayRepeater = new Horde_Date_Parser_Locale_Base_Repeater_DayName(Horde_Date::DATE_SUNDAY);
-            $sundayRepeater->start = $this->now;
-            $lastSundaySpan = $sundayRepeater->next('past');
-            $thisWeekStart = $lastSundaySpan->begin;
-            $thisWeekEnd = clone($thisWeekStart);
-            $thisWeekEnd->day += 7;
-            return new Horde_Date_Span($thisWeekStart, $thisWeekEnd);
-        }
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-        return $span->add(array('day' => $direction * $amount * 7));
-    }
-
-    public function width()
-    {
-        return self::WEEK_SECONDS;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-week';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Weekend.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Weekend.php
deleted file mode 100644 (file)
index 17b227e..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Weekend extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    /**
-     * (2 * 24 * 60 * 60)
-     */
-    const WEEKEND_SECONDS = 172800;
-
-    public $currentWeekStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        if ($this->currentWeekStart) {
-            switch ($pointer) {
-            case 'future':
-                $saturdayRepeater = new Horde_Date_Locale_Base_Repeater_DayName(Horde_Date::DATE_SATURDAY);
-                $saturdayRepeater->start = $this->now;
-                $nextSaturdaySpan = $saturdayRepeater->next('future');
-                $this->currentWeekStart = $nextSaturdaySpan->begin;
-                break;
-
-            case 'past':
-                $saturdayRepeater = new Horde_Date_Locale_Base_Repeater_DayName(Horde_Date::DATE_SATURDAY);
-                $saturdayRepeater->start = $this->now;
-                $saturdayRepeater->start->day++;
-                $lastSaturdaySpan = $saturdayRepeater->next('past');
-                $this->currentWeekStart = $lastSaturdaySpan->begin;
-                break;
-            }
-        } else {
-            $direction = ($pointer == 'future') ? 1 : -1;
-            $this->currentWeekStart->day += $direction * 7;
-        }
-
-        $currentWeekEnd = clone($this->currentWeekStart);
-        $currentWeekEnd->day += 2;
-        return new Horde_Date_Span($this->currentWeekStart, $currentWeekEnd);
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'future':
-        case 'none':
-            $saturdayRepeater = new Horde_Date_Locale_Base_Repeater_DayName(Horde_Date::DATE_SATURDAY);
-            $saturdayRepeater->start = $this->now;
-            $thisSaturdaySpan = $saturdayRepeater->this('future');
-            $thisSaturdaySpanEnd = $thisSaturdaySpan->begin;
-            $thisSaturdaySpanEnd->day += 2;
-            return new Horde_Date_Span($thisSaturdaySpan->begin, $thisSaturdaySpanEnd);
-
-        case 'past':
-            $saturdayRepeater = new Horde_Date_Locale_Base_Repeater_DayName(Horde_Date::DATE_SATURDAY);
-            $saturdayRepeater->start = $this->now;
-            $lastSaturdaySpan = $saturdayRepeater->this('past');
-            $lastSaturdaySpanEnd = $lastSaturdaySpan->begin;
-            $lastSaturdaySpanEnd->day += 2;
-            return new Horde_Date_Span($lastSaturdaySpan->begin, $lastSaturdaySpanEnd);
-        }
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-        $weekend = new Horde_Date_Parser_Locale_Base_Repeater_Weekend('weekend');
-        $weekend->start = $span->begin;
-        $start = $weekend->next($pointer)->begin;
-        $start->day += ($amount - 1) * $direction * 7;
-        // @FIXME
-        return new Horde_Date_Span($start, $start + ($span->end - $span->begin));
-    }
-
-    public function width()
-    {
-        return self::WEEKEND_SECONDS;
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-weekend';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Year.php b/framework/Date_Parser/lib/Horde/Date/Parser/Locale/Base/Repeater/Year.php
deleted file mode 100644 (file)
index 87151f8..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-class Horde_Date_Parser_Locale_Base_Repeater_Year extends Horde_Date_Parser_Locale_Base_Repeater
-{
-    public $currentYearStart;
-
-    public function next($pointer)
-    {
-        parent::next($pointer);
-
-        if (!$this->currentYearStart) {
-            switch ($pointer) {
-            case 'future':
-                $this->currentYearStart = new Horde_Date(array('year' => $this->now->year + 1));
-                break;
-
-            case 'past':
-                $this->currentYearStart = new Horde_Date(array('year' => $this->now->year - 1));
-                break;
-            }
-        } else {
-            $diff = ($pointer == 'future') ? 1 : -1;
-            $this->currentYearStart->year += $diff;
-        }
-
-        return new Horde_Date_Span($this->currentYearStart, new Horde_Date(array('year' => $this->currentYearStart->year + 1)));
-    }
-
-    public function this($pointer = 'future')
-    {
-        parent::this($pointer);
-
-        switch ($pointer) {
-        case 'future':
-            $thisYearStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1));
-            $thisYearEnd = new Horde_Date(array('year' => $this->now->year + 1));
-            break;
-
-        case 'past':
-            $thisYearStart = new Horde_Date(array('year' => $this->now->year));
-            $thisYearEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
-            break;
-
-        case 'none':
-            $thisYearStart = new Horde_Date(array('year' => $this->now->year));
-            $thisYearEnd = new Horde_Date(array('year' => $this->now->year + 1));
-            break;
-        }
-
-        return new Horde_Date_Span($thisYearStart, $thisYearEnd);
-    }
-
-    public function offset($span, $amount, $pointer)
-    {
-        $direction = ($pointer == 'future') ? 1 : -1;
-
-        $sb = clone($span->begin);
-        $sb->year += ($amount * $direction);
-
-        $se = clone($span->end);
-        $se->year += ($amount * $direction);
-
-        return new Horde_Date_Span($se, $sb);
-    }
-
-    public function width()
-    {
-        return (365 * 24 * 60 * 60);
-    }
-
-    public function __toString()
-    {
-        return parent::__toString() . '-year';
-    }
-
-}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater.php b/framework/Date_Parser/lib/Horde/Date/Repeater.php
new file mode 100644 (file)
index 0000000..43ec167
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ */
+
+/**
+ */
+abstract class Horde_Date_Repeater
+{
+    /**
+     * returns the width (in seconds or months) of this repeatable.
+     */
+    abstract public function width();
+
+    /**
+     * returns the next occurance of this repeatable.
+     */
+    public function next($pointer)
+    {
+        if (is_null($this->now)) {
+            throw new Horde_Date_Repeater_Exception('Start point must be set before calling next()');
+        }
+
+        if (!in_array($pointer, array('future', 'none', 'past'))) {
+            throw new Horde_Date_Repeater_Exception("First argument 'pointer' must be one of 'past', 'future', 'none'");
+        }
+    }
+
+    public function this($pointer)
+    {
+        if (is_null($this->now)) {
+            throw new Horde_Date_Repeater_Exception('Start point must be set before calling this()');
+        }
+
+        if (!in_array($pointer, array('future', 'none', 'past'))) {
+            throw new Horde_Date_Repeater_Exception("First argument 'pointer' must be one of 'past', 'future', 'none'");
+        }
+    }
+
+    public function __toString()
+    {
+        return 'repeater';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Day.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Day.php
new file mode 100644 (file)
index 0000000..6b6ef05
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+class Horde_Date_Repeater_Day extends Horde_Date_Repeater
+{
+    // (24 * 60 * 60)
+    const DAY_SECONDS = 86400;
+
+    public $currentDayStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        if (!$this->currentDayStart) {
+            $this->currentDayStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
+        }
+
+        $direction = ($pointer == 'future') ? 1 : -1;
+        $this->currentDayStart->day += $direction;
+
+        $end = clone($this->currentDayStart);
+        $end->day += 1;
+
+        return new Horde_Date_Span($this->currentDayStart, $end);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'future':
+            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour + 1));
+            $dayEnd = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day + 1));
+            break;
+
+        case 'past':
+            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day));
+            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour));
+            break;
+
+        case 'none':
+            $dayBegin = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day));
+            $dayEnd = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day + 1));
+            break;
+        }
+
+        return new Horde_Date_Span($dayBegin, $dayEnd);
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+        return $span->add(array('day' => $direction * $amount));
+    }
+
+    public function width()
+    {
+        return self::DAY_SECONDS;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-day';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/DayName.php b/framework/Date_Parser/lib/Horde/Date/Repeater/DayName.php
new file mode 100644 (file)
index 0000000..fe886e6
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+class Horde_Date_Repeater_DayName extends Horde_Date_Repeater
+{
+    // (24 * 60 * 60)
+    const DAY_SECONDS = 86400;
+
+    public $currentDayStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        $direction = ($pointer == 'future') ? 1 : -1;
+
+        if (!$this->currentDayStart) {
+            $this->currentDayStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + $direction));
+
+            $dayNum = $this->type;
+            while ($this->currentDayStart->dayOfWeek() != $dayNum) {
+                $this->currentDayStart->day += $direction;
+            }
+        } else {
+            $this->currentDayStart->day += $direction * 7;
+        }
+
+        $end = clone($this->currentDayStart);
+        $end->day++;
+        return new Horde_Date_Span($this->currentDayStart, $end);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::next($pointer);
+
+        if ($pointer == 'none') {
+            $pointer = 'future';
+        }
+        return $this->next($pointer);
+    }
+
+    public function width()
+    {
+        return self::DAY_SECONDS;
+    }
+
+    public function __toString()
+    {
+        $dayStrings = array(
+            Horde_Date::DATE_MONDAY => 'monday',
+            Horde_Date::DATE_TUESDAY => 'tuesday',
+            Horde_Date::DATE_WEDNESDAY => 'wednesday',
+            Horde_Date::DATE_THURSDAY => 'thursday',
+            Horde_Date::DATE_FRIDAY => 'friday',
+            Horde_Date::DATE_SATURDAY => 'saturday',
+            Horde_Date::DATE_SUNDAY => 'sunday',
+        );
+        return parent::__toString() . '-dayname-' . $dayStrings[$this->type];
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/DayPortion.php b/framework/Date_Parser/lib/Horde/Date/Repeater/DayPortion.php
new file mode 100644 (file)
index 0000000..e03a637
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+class Horde_Date_Repeater_DayPortion extends Horde_Date_Repeater
+{
+    /**
+     * 6am-12am (6 * 60 * 60, 12 * 60 * 60)
+     */
+    public static $morning = array(21600, 43200);
+
+    /**
+     * 1pm-5pm (13 * 60 * 60, 17 * 60 * 60)
+     */
+    public static $afternoon = array(46800, 61200);
+
+    /**
+     * 5pm-8pm (17 * 60 * 60, 20 * 60 * 60)
+     */
+    public static $evening = array(61200, 72000);
+
+    /**
+     * 8pm-12pm (20 * 60 * 60, 24 * 60 * 60)
+     */
+    public static $night = array(72000, 86400);
+
+    public $range;
+    public $currentSpan;
+
+    public function __construct($type)
+    {
+        parent::__construct($type);
+
+        if (is_int($type)) {
+            $this->range = array(($type * 3600), (($type + 12) * 3600));
+        } else {
+            $lookup = array(
+                'am' => array(0, (12 * 3600 - 1)),
+                'pm' => array((12 * 3600), (24 * 3600 - 1)),
+                'morning' => self::$morning,
+                'afternoon' => self::$afternoon,
+                'evening' => self::$evening,
+                'night' => self::$night,
+            );
+            if (!isset($lookup[$type])) {
+                throw new InvalidArgumentException("Invalid type '$type' for Repeater_DayPortion");
+            }
+            $this->range = $lookup[$type];
+        }
+    }
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        $fullDay = 60 * 60 * 24;
+
+        if (!$this->currentSpan) {
+            $nowSeconds = $this->now->hour * 3600 + $this->now->min * 60 + $this->now->sec;
+            if ($nowSeconds < $this->range[0]) {
+                switch ($pointer) {
+                case 'future':
+                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day, 'sec' => $this->range[0]));
+                    break;
+
+                case 'past':
+                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day - 1, 'sec' => $this->range[0]));
+                    break;
+                }
+            } elseif ($nowSeconds > $this->range[1]) {
+                switch ($pointer) {
+                case 'future':
+                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1, 'sec' => $this->range[0]));
+                    break;
+
+                case 'past':
+                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day, 'sec' => $this->range[0]));
+                    break;
+                }
+            } else {
+                switch ($pointer) {
+                case 'future':
+                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1, 'sec' => $this->range[0]));
+                    break;
+
+                case 'past':
+                    $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day - 1, 'sec' => $this->range[0]));
+                    break;
+                }
+            }
+
+            $rangeEnd = new Horde_Date(array('year' => $rangeStart->year, 'month' => $rangeStart->month, 'day' => $rangeStart->day, 'sec' => $this->range[1] - $this->range[0]));
+            $this->currentSpan = new Horde_Date_Span($rangeStart, $rangeEnd);
+        } else {
+            switch ($pointer) {
+            case 'future':
+                $this->currentSpan = $this->currentSpan->add(array('day' => 1));
+                break;
+
+            case 'past':
+                $this->currentSpan = $this->currentSpan->add(array('day' => -1));
+                break;
+            }
+        }
+
+        return $this->currentSpan;
+    }
+
+    public function this($context = 'future')
+    {
+        parent::super($context);
+
+        $rangeStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day, 'sec' => $this->range[0]));
+        $rangeEnd = new Horde_Date(array('year' => $rangeStart->year, 'month' => $rangeStart->month, 'day' => $rangeStart->day, 'sec' => $this->range[1] - $this->range[0]));
+        $this->currentSpan = new Horde_Date_Span($rangeStart, $rangeEnd);
+        return $this->currentSpan;
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $this->now = $span->begin;
+        $portionSpan = $this->next($pointer);
+        $direction = ($pointer == 'future') ? 1 : -1;
+        return $portionSpan + ($direction * ($amount - 1) * Horde_Date_Repeater_Day::DAY_SECONDS);
+    }
+
+    public function width()
+    {
+        if (!$this->range) {
+            throw new Horde_Date_Repeater_Exception('Range has not been set');
+        }
+
+        if ($this->currentSpan) {
+            return $this->currentSpan->width();
+        }
+
+        if (is_int($this->type)) {
+            return (12 * 3600);
+        } else {
+            return $this->range[1] - $this->range[0];
+        }
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-dayportion-' . $this->type;
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Exception.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Exception.php
new file mode 100644 (file)
index 0000000..0fb573e
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+class Horde_Date_Repeater_Exception extends Exception
+{
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Hour.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Hour.php
new file mode 100644 (file)
index 0000000..e501a10
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+class Horde_Date_Repeater_Hour extends Horde_Date_Repeater
+{
+    public $currentHourStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        $direction = ($pointer == 'future') ? 1 : -1;
+        if (!$this->currentHourStart) {
+            $this->currentHourStart = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour));
+        }
+        $this->currentHourStart->hour += $direction;
+
+        $end = clone($this->currentHourStart);
+        $end->hour++;
+        return new Horde_Date_Span($this->currentHourStart, $end);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'future':
+            $hourStart = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min + 1));
+            $hourEnd = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour + 1));
+            break;
+
+        case 'past':
+            $hourStart = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour));
+            $hourEnd = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour + 1, 'min' => $this->now->min));
+            break;
+
+        case 'none':
+            $hourStart = new Horde_Date(array('year' => $this->month->year, 'month' => $this->now->month, 'day' => $this->now->day, 'hour' => $this->now->hour));
+            $hourEnd = clone($hourStart);
+            $hourEnd->hour++;
+            break;
+        }
+
+        return new Horde_Date_Span($hourStart, $hourEnd);
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+        return $span->add(array('hour' => $direction * $amount));
+    }
+
+    public function width()
+    {
+        return 3600;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-hour';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Minute.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Minute.php
new file mode 100644 (file)
index 0000000..447825d
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+class Horde_Date_Repeater_Minute extends Horde_Date_Repeater
+{
+    public $currentMinuteStart;
+
+    public function next($pointer = 'future')
+    {
+        parent::next($pointer);
+
+        if (!$this->currentMinuteStart) {
+            $this->currentMinuteStart = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
+        }
+        $direction = ($pointer == 'future') ? 1 : -1;
+        $this->currentMinuteStart->min += $direction;
+
+        $end = clone($this->currentMinuteStart);
+        $end->min++;
+        return new Horde_Date_Span($this->currentMinuteStart, $end);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'future':
+            $minuteBegin = clone($this->now);
+            $minuteEnd = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
+            break;
+
+        case 'past':
+            $minuteBegin = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
+            $minuteEnd = clone($this->now);
+            break;
+
+        case 'none':
+            $minuteBegin = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min));
+            $minuteEnd = new Horde_Date(array('month' => $this->now->month, 'year' => $this->now->year, 'day' => $this->now->day, 'hour' => $this->now->hour, 'min' => $this->now->min + 1));
+            break;
+        }
+
+        return new Horde_Date_Span($minuteBegin, $minuteEnd);
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+        return $span->add(array('min' => $diretion * $amount));
+    }
+
+    public function width()
+    {
+        return 60;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-minute';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Month.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Month.php
new file mode 100644 (file)
index 0000000..fcb8f85
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+class Horde_Date_Repeater_Month extends Horde_Date_Repeater
+{
+    /**
+     * 30 * 24 * 60 * 60
+     */
+    const MONTH_SECONDS = 2592000;
+
+    public $currentMonthStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        if (!$this->currentMonthStart) {
+            $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month));
+        }
+        $direction = ($pointer == 'future') ? 1 : -1;
+        $this->currentMonthStart->month += $direction;
+
+        $end = clone($this->currentMonthStart);
+        $end->month++;
+        return new Horde_Date_Span($this->currentMonthStart, $end);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'future':
+            $monthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1));
+            $monthEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month + 1));
+            break;
+
+        case 'past':
+            $monthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month));
+            $monthEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
+            break;
+
+        case 'none':
+            $monthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month));
+            $monthEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month + 1));
+            break;
+        }
+
+        return new Horde_Date_Span($monthStart, $monthEnd);
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+        return $span->add(array('month' => $amount * $direction));
+    }
+
+    public function width()
+    {
+        return self::MONTH_SECONDS;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-month';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/MonthName.php b/framework/Date_Parser/lib/Horde/Date/Repeater/MonthName.php
new file mode 100644 (file)
index 0000000..e1f21e2
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+class Horde_Date_Repeater_MonthName extends Horde_Date_Repeater
+{
+    public $currentMonthStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        if (!$this->currentMonthStart) {
+            $targetMonth = $this->_monthNumber($this->type);
+            switch ($pointer) {
+            case 'future':
+                if ($this->now->month > $targetMonth) {
+                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $targetMonth));
+                } else {
+                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year + 1, 'month' => $targetMonth));
+                }
+                break;
+
+            case 'none':
+                if ($this->now->month <= $targetMonth) {
+                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $targetMonth));
+                } else {
+                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year + 1, 'month' => $targetMonth));
+                }
+                break;
+
+            case 'past':
+                if ($this->now->month > $targetMonth) {
+                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year, 'month' => $targetMonth));
+                } else {
+                    $this->currentMonthStart = new Horde_Date(array('year' => $this->now->year - 1, 'month' => $targetMonth));
+                }
+                break;
+            }
+        } else {
+            switch ($pointer) {
+            case 'future':
+                $this->currentMonthStart->year++;
+                break;
+
+            case 'past':
+                $this->currentMonthStart->year--;
+                break;
+            }
+        }
+
+        return new Horde_Date_Span($this->currentMonthStart, new Horde_Date(array('year' => $this->currentMonthStart->year, 'month' => $this->currentMonthStart->month + 1)));
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'past':
+            return $this->next($pointer);
+
+        case 'future':
+        case 'none':
+            return $this->next('none');
+        }
+    }
+
+    public function width()
+    {
+        return Horde_Date_Repeater_Month::MONTH_SECONDS;
+    }
+
+    public function index()
+    {
+        return $this->_monthNumber($this->type);
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-monthname-' . $this->type;
+    }
+
+    protected function _monthNumber($monthName)
+    {
+        $months = array(
+            'january' => 1,
+            'february' => 2,
+            'march' => 3,
+            'april' => 4,
+            'may' => 5,
+            'june' => 6,
+            'july' => 7,
+            'august' => 8,
+            'september' => 9,
+            'october' => 10,
+            'november' => 11,
+            'december' => 12,
+        );
+        if (!isset($months[$monthName])) {
+            throw new InvalidArgumentException('Invalid month name "' . $monthName . '"');
+        }
+        return $months[$monthName];
+    }
+
+}
\ No newline at end of file
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Season.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Season.php
new file mode 100644 (file)
index 0000000..2ad200b
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+class Horde_Date_Repeater_Season extends Horde_Date_Repeater
+{
+    /**
+     * 91 * 24 * 60 * 60
+     */
+    const SEASON_SECONDS = 7862400;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+        throw new Horde_Date_Repeater_Exception('Not implemented');
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+        throw new Horde_Date_Repeater_Exception('Not implemented');
+    }
+
+    public function width()
+    {
+        return self::SEASON_SECONDS;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-season';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/SeasonName.php b/framework/Date_Parser/lib/Horde/Date/Repeater/SeasonName.php
new file mode 100644 (file)
index 0000000..d462ce1
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+class Horde_Date_Repeater_SeasonName extends Horde_Date_Repeater_Season
+{
+    /**
+     * 91 * 24 * 60 * 60
+     */
+    const SEASON_SECONDS = 7862400;
+
+    public $summer = array('jul 21', 'sep 22');
+    public $autumn = array('sep 23', 'dec 21');
+    public $winter = array('dec 22', 'mar 19');
+    public $spring = array('mar 20', 'jul 20');
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+        throw new Horde_Date_Repeater_Exception('Not implemented');
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+        throw new Horde_Date_Repeater_Exception('Not implemented');
+    }
+
+    public function width()
+    {
+        return self::SEASON_SECONDS;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-season-' . $this->type;
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Second.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Second.php
new file mode 100644 (file)
index 0000000..a789d3d
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+class Horde_Date_Repeater_Second extends Horde_Date_Repeater
+{
+    public $secondStart;
+
+    public function next($pointer = 'future')
+    {
+        parent::next($pointer);
+
+        $direction = ($pointer == 'future') ? 1 : -1;
+
+        if (!$this->secondStart) {
+            $this->secondStart = clone($this->now);
+            $this->secondStart->sec += $direction;
+        } else {
+            $this->secondStart += $direction;
+        }
+
+        $end = clone($this->secondStart);
+        $end->sec++;
+        return new Horde_Date_Span($this->secondStart, $end);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        $end = clone($this->now);
+        $end->sec++;
+        return new Horde_Date_Span($this->now, $end);
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+        return $span->add($direction * $amount);
+    }
+
+    public function width()
+    {
+        return 1;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-second';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Time.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Time.php
new file mode 100644 (file)
index 0000000..67147c1
--- /dev/null
@@ -0,0 +1,162 @@
+<?php
+class Horde_Date_Repeater_Time extends Horde_Date_Repeater
+{
+    public $currentTime;
+
+    public function __construct($time, $options = array())
+    {
+        $t = str_replace(':', '', $time);
+
+        switch (strlen($t)) {
+        case 1:
+        case 2:
+            $hours = (int)$t;
+            $this->type = ($hours == 12) ?
+                new Horde_Date_Tick(0, true) :
+                new Horde_Date_Tick($hours * 3600, true);
+            break;
+
+        case 3:
+            $this->type = new Horde_Date_Tick($t[0] * 3600 + (int)substr($t, 1, 2) * 60, true);
+            break;
+
+        case 4:
+            $ambiguous = (strpos($time, ':') !== false) && ($t[0] != 0) && ((int)substr($t, 0, 2) <= 12);
+            $hours = (int)substr($t, 0, 2);
+            $this->type = ($hours == 12) ?
+                new Horde_Date_Tick((int)substr($t, 2, 2) * 60, $ambiguous) :
+                new Horde_Date_Tick($hours * 60 * 60 + (int)substr($t, 2, 2) * 60, $ambiguous);
+            break;
+
+        case 5:
+            $this->type = new Horde_Date_Tick($t[0] * 3600 + (int)substr($t, 1, 2) * 60 + (int)substr($t, 3, 2), true);
+            break;
+
+        case 6:
+            $ambiguous = (strpos($time, ':') !== false) && ($t[0] != 0) && ((int)substr($t, 0, 2) <= 12);
+            $hours = (int)substr($t, 0, 2);
+            $this->type = ($hours == 12) ?
+                new Horde_Date_Tick((int)substr($t, 2, 2) * 60 + (int)substr($t, 4, 2), $ambiguous) :
+                new Horde_Date_Tick($hours * 60 * 60 + (int)substr($t, 2, 2) * 60 + (int)substr($t, 4, 2), $ambiguous);
+            break;
+
+        default:
+            throw new Horde_Date_Repeater_Exception('Time cannot exceed six digits');
+        }
+    }
+
+    /**
+     * Return the next past or future Span for the time that this Repeater represents
+     *   pointer - Symbol representing which temporal direction to fetch the next day
+     *             must be either :past or :future
+     */
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        $halfDay = 3600 * 12;
+        $fullDay = 3600 * 24;
+
+        $first = false;
+
+        if (!$this->currentTime) {
+            $first = true;
+            $midnight = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
+            $yesterdayMidnight = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day - 1));
+            $tomorrowMidnight = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1));
+
+            if ($pointer == 'future') {
+                if ($this->type->ambiguous) {
+                    foreach (array($midnight + $this->type, $midnight + $halfDay + $this->type, $tomorrowMidnight + $this->type) as $t) {
+                        if ($t >= $this->now) {
+                            $this->currentTime = $t;
+                            break;
+                        }
+                    }
+                } else {
+                    foreach (array($midnight + $this->type, $tomorrowMidnight + $this->type) as $t) {
+                        if ($t >= $this->now) {
+                            $this->currentTime = $t;
+                            break;
+                        }
+                    }
+                }
+            } else {
+                if ($this->type->ambiguous) {
+                    foreach (array($midnight + $halfDay + $this->type, $midnight + $this->type, $yesterdayMidnight + $this->type * 2) as $t) {
+                        if ($t <= $this->now) {
+                            $this->currentTime = $t;
+                            break;
+                        }
+                    }
+                } else {
+                    foreach (array($midnight + $this->type, $yesterdayMidnight + $this->type) as $t) {
+                        if ($t <= $this->now) {
+                            $this->currentTime = $t;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (!$this->currentTime) {
+                throw new Horde_Date_Repeater_Exception('Current time cannot be null at this point');
+            }
+        }
+
+        if (!$first) {
+            $increment = $this->type->ambiguous ? $halfday : $fullDay;
+            $this->currentTime += ($pointer == 'future') ? $increment : -$increment;
+        }
+
+        return new Horde_Date_Span($this->currentTime, $this->currentTime + $this->width());
+    }
+
+    public function this($context = 'future')
+    {
+        parent::this($context);
+
+        if ($context == 'none') { $context = 'future'; }
+        return $this->next($context);
+    }
+
+    public function width()
+    {
+        return 1;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-time-' . $this->type;
+    }
+
+}
+
+class Horde_Date_Tick
+{
+    public $time;
+    public $ambiguous;
+
+    public function __construct($time, $ambiguous = false)
+    {
+        $this->time = $time;
+        $this->ambiguous = $ambiguous;
+    }
+
+    public function mult($other)
+    {
+        return new Horde_Date_Tick($this->time * $other, $this->ambiguous);
+    }
+
+    /*
+    def to_f
+      @time.to_f
+    end
+    */
+
+    public function __toString()
+    {
+        return $this->time . ($this->ambiguous ? '?' : '');
+    }
+
+}
\ No newline at end of file
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Week.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Week.php
new file mode 100644 (file)
index 0000000..9b80b78
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+class Horde_Date_Repeater_Week extends Horde_Date_Repeater
+{
+    /**
+     * (7 * 24 * 60 * 60)
+     */
+    const WEEK_SECONDS = 604800;
+
+    public $currentWeekStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        if (!$this->currentWeekStart) {
+            switch ($pointer) {
+            case 'future':
+                $sundayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SUNDAY);
+                $sundayRepeater->now = $this->now;
+                $nextSundaySpan = $sundayRepeater->next('future');
+                $this->currentWeekStart = $nextSundaySpan->begin;
+                break;
+
+            case 'past':
+                $sundayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SUNDAY);
+                $sundayRepeater->now = clone($this->now);
+                $sundayRepeater->now->day++;
+                $sundayRepeater->next('past');
+                $lastSundaySpan = $sundayRepeater->next('past');
+                $currentWeekStart = $lastSundaySpan->begin;
+                break;
+            }
+        } else {
+            $direction = ($pointer == 'future') ? 1 : -1;
+            $this->currentWeekStart->day += $direction * 7;
+        }
+
+        $end = clone($this->currentWeekStart);
+        $end->day += 7;
+        return new Horde_Date_Span($this->currentWeekStart, $end);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'future':
+            $thisWeekStart = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour + 1));
+            $sundayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SUNDAY);
+            $sundayRepeater->now = $this->now;
+            $thisSundaySpan = $sundayRepeater->this('future');
+            $thisWeekEnd = $thisSundaySpan->begin;
+            return new Horde_Date_Span($thisWeekStart, $thisWeekEnd);
+
+        case 'past':
+            $thisWeekEnd = new Horde_Date(array('year' => $now->year, 'month' => $now->month, 'day' => $now->day, 'hour' => $now->hour));
+            $sundayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SUNDAY);
+            $sundayRepeater->now = $this->now;
+            $lastSundaySpan = $sundayRepeater->next('past');
+            $thisWeekStart = $lastSundaySpan->begin;
+            return new Horde_Date_Span($thisWeekStart, $thisWeekEnd);
+
+        case 'none':
+            $sundayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SUNDAY);
+            $sundayRepeater->now = $this->now;
+            $lastSundaySpan = $sundayRepeater->next('past');
+            $thisWeekStart = $lastSundaySpan->begin;
+            $thisWeekEnd = clone($thisWeekStart);
+            $thisWeekEnd->day += 7;
+            return new Horde_Date_Span($thisWeekStart, $thisWeekEnd);
+        }
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+        return $span->add(array('day' => $direction * $amount * 7));
+    }
+
+    public function width()
+    {
+        return self::WEEK_SECONDS;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-week';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Weekend.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Weekend.php
new file mode 100644 (file)
index 0000000..edc48fa
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+class Horde_Date_Repeater_Weekend extends Horde_Date_Repeater
+{
+    /**
+     * (2 * 24 * 60 * 60)
+     */
+    const WEEKEND_SECONDS = 172800;
+
+    public $currentWeekStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        if ($this->currentWeekStart) {
+            switch ($pointer) {
+            case 'future':
+                $saturdayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SATURDAY);
+                $saturdayRepeater->now = $this->now;
+                $nextSaturdaySpan = $saturdayRepeater->next('future');
+                $this->currentWeekStart = $nextSaturdaySpan->begin;
+                break;
+
+            case 'past':
+                $saturdayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SATURDAY);
+                $saturdayRepeater->now = $this->now;
+                $saturdayRepeater->now->day++;
+                $lastSaturdaySpan = $saturdayRepeater->next('past');
+                $this->currentWeekStart = $lastSaturdaySpan->begin;
+                break;
+            }
+        } else {
+            $direction = ($pointer == 'future') ? 1 : -1;
+            $this->currentWeekStart->day += $direction * 7;
+        }
+
+        $currentWeekEnd = clone($this->currentWeekStart);
+        $currentWeekEnd->day += 2;
+        return new Horde_Date_Span($this->currentWeekStart, $currentWeekEnd);
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'future':
+        case 'none':
+            $saturdayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SATURDAY);
+            $saturdayRepeater->now = $this->now;
+            $thisSaturdaySpan = $saturdayRepeater->this('future');
+            $thisSaturdaySpanEnd = $thisSaturdaySpan->begin;
+            $thisSaturdaySpanEnd->day += 2;
+            return new Horde_Date_Span($thisSaturdaySpan->begin, $thisSaturdaySpanEnd);
+
+        case 'past':
+            $saturdayRepeater = new Horde_Date_Repeater_DayName(Horde_Date::DATE_SATURDAY);
+            $saturdayRepeater->now = $this->now;
+            $lastSaturdaySpan = $saturdayRepeater->this('past');
+            $lastSaturdaySpanEnd = $lastSaturdaySpan->begin;
+            $lastSaturdaySpanEnd->day += 2;
+            return new Horde_Date_Span($lastSaturdaySpan->begin, $lastSaturdaySpanEnd);
+        }
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+        $weekend = new Horde_Date_Repeater_Weekend('weekend');
+        $weekend->now = $span->begin;
+        $start = $weekend->next($pointer)->begin;
+        $start->day += ($amount - 1) * $direction * 7;
+        // @FIXME
+        return new Horde_Date_Span($start, $start + ($span->end - $span->begin));
+    }
+
+    public function width()
+    {
+        return self::WEEKEND_SECONDS;
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-weekend';
+    }
+
+}
diff --git a/framework/Date_Parser/lib/Horde/Date/Repeater/Year.php b/framework/Date_Parser/lib/Horde/Date/Repeater/Year.php
new file mode 100644 (file)
index 0000000..ace5cdc
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+class Horde_Date_Repeater_Year extends Horde_Date_Repeater
+{
+    public $currentYearStart;
+
+    public function next($pointer)
+    {
+        parent::next($pointer);
+
+        if (!$this->currentYearStart) {
+            switch ($pointer) {
+            case 'future':
+                $this->currentYearStart = new Horde_Date(array('year' => $this->now->year + 1));
+                break;
+
+            case 'past':
+                $this->currentYearStart = new Horde_Date(array('year' => $this->now->year - 1));
+                break;
+            }
+        } else {
+            $diff = ($pointer == 'future') ? 1 : -1;
+            $this->currentYearStart->year += $diff;
+        }
+
+        return new Horde_Date_Span($this->currentYearStart, new Horde_Date(array('year' => $this->currentYearStart->year + 1)));
+    }
+
+    public function this($pointer = 'future')
+    {
+        parent::this($pointer);
+
+        switch ($pointer) {
+        case 'future':
+            $thisYearStart = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day + 1));
+            $thisYearEnd = new Horde_Date(array('year' => $this->now->year + 1));
+            break;
+
+        case 'past':
+            $thisYearStart = new Horde_Date(array('year' => $this->now->year));
+            $thisYearEnd = new Horde_Date(array('year' => $this->now->year, 'month' => $this->now->month, 'day' => $this->now->day));
+            break;
+
+        case 'none':
+            $thisYearStart = new Horde_Date(array('year' => $this->now->year));
+            $thisYearEnd = new Horde_Date(array('year' => $this->now->year + 1));
+            break;
+        }
+
+        return new Horde_Date_Span($thisYearStart, $thisYearEnd);
+    }
+
+    public function offset($span, $amount, $pointer)
+    {
+        $direction = ($pointer == 'future') ? 1 : -1;
+
+        $sb = clone($span->begin);
+        $sb->year += ($amount * $direction);
+
+        $se = clone($span->end);
+        $se->year += ($amount * $direction);
+
+        return new Horde_Date_Span($se, $sb);
+    }
+
+    public function width()
+    {
+        return (365 * 24 * 60 * 60);
+    }
+
+    public function __toString()
+    {
+        return parent::__toString() . '-year';
+    }
+
+}