Index: tests/core/ScheduledTask.test.php
===================================================================
--- tests/core/ScheduledTask.test.php	(revision 0)
+++ tests/core/ScheduledTask.test.php	(revision 0)
@@ -0,0 +1,34 @@
+<?php
+if(!defined("PIWIK_PATH_TEST_TO_ROOT")) {
+	define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../..');
+}
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+	require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
+}
+
+require_once 'ScheduledTask.php';
+
+class Test_Piwik_ScheduledTask extends UnitTestCase
+{
+	public function test_getClassName()
+	{
+		$scheduledTask = new Piwik_ScheduledTask ( "className", null, null );
+		$className = $scheduledTask->getClassName();
+		$this->assertTrue( is_string($className) && !empty($className) );
+	}
+	
+	public function test_getMethodName()
+	{
+		$scheduledTask = new Piwik_ScheduledTask ( null, "methodname", null );
+		$methodName = $scheduledTask->getMethodName();
+		$this->assertTrue( is_string($methodName) && !empty($methodName) );
+	}
+	
+	public function test_getScheduledTime()
+	{
+		$scheduledTask = new Piwik_ScheduledTask ( null, null, new Piwik_ScheduledTime_Hourly() );
+		$scheduledTime = $scheduledTask->getScheduledTime();
+		$this->assertTrue( get_class($scheduledTime) == "Piwik_ScheduledTime_Hourly" );
+	}	
+}
\ No newline at end of file
Index: tests/core/ScheduledTime.test.php
===================================================================
--- tests/core/ScheduledTime.test.php	(revision 0)
+++ tests/core/ScheduledTime.test.php	(revision 0)
@@ -0,0 +1,1274 @@
+<?php
+if(!defined("PIWIK_PATH_TEST_TO_ROOT")) {
+	define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../..');
+}
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+	require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
+}
+
+require_once 'ScheduledTime.php';
+require_once 'ScheduledTime/Hourly.php';
+require_once 'ScheduledTime/Daily.php';
+require_once 'ScheduledTime/Weekly.php';
+require_once 'ScheduledTime/Monthly.php';
+
+Mock::generatePartial('Piwik_ScheduledTime_Hourly', 'Piwik_ScheduledTime_Hourly_Test', array('getTime'));
+Mock::generatePartial('Piwik_ScheduledTime_Daily', 'Piwik_ScheduledTime_Daily_Test', array('getTime'));
+Mock::generatePartial('Piwik_ScheduledTime_Weekly', 'Piwik_ScheduledTime_Weekly_Test', array('getTime'));
+Mock::generatePartial('Piwik_ScheduledTime_Monthly', 'Piwik_ScheduledTime_Monthly_Test', array('getTime'));
+
+class Test_Piwik_ScheduledTime extends UnitTestCase
+{
+	private $JANUARY_01_1971_09_00_00;
+	private $JANUARY_01_1971_09_10_00;
+	private $JANUARY_01_1971_10_00_00;
+	private $JANUARY_01_1971_10_10_00;
+	private $JANUARY_01_1971_11_00_00;
+	private $JANUARY_01_1971_12_00_00;
+	private $JANUARY_01_1971_12_10_00;
+	
+	private $JANUARY_02_1971_09_00_00;
+	private $JANUARY_02_1971_09_10_00;
+	private $JANUARY_02_1971_12_10_00;
+	
+	private $JANUARY_03_1971_12_10_00;
+	
+	private $JANUARY_04_1971_09_00_00;
+	private $JANUARY_04_1971_09_10_00;
+	private $JANUARY_04_1971_12_10_00;
+	
+	private $JANUARY_05_1971_09_00_00;
+	private $JANUARY_05_1971_09_10_00;
+	private $JANUARY_05_1971_12_00_00;
+	
+	private $JANUARY_08_1971_09_00_00;
+	private $JANUARY_08_1971_09_10_00;
+	
+	private $JANUARY_09_1971_09_00_00;
+	private $JANUARY_09_1971_09_10_00;
+	
+	private $JANUARY_11_1971_09_00_00;
+	private $JANUARY_11_1971_09_10_00;
+	
+	private $JANUARY_12_1971_09_00_00;
+	private $JANUARY_18_1971_09_00_00;
+	private $JANUARY_19_1971_09_00_00;
+	
+	private $JANUARY_25_1971_09_00_00;
+	private $JANUARY_26_1971_09_00_00;
+	
+	private $FEBRUARY_01_1971_09_00_00;
+	private $FEBRUARY_02_1971_09_00_00;
+	private $FEBRUARY_03_1971_09_00_00;
+	private $FEBRUARY_03_1971_12_10_00;
+	private $FEBRUARY_04_1971_09_00_00;
+	private $FEBRUARY_04_1971_12_10_00;
+	private $FEBRUARY_05_1971_09_00_00;
+	private $FEBRUARY_08_1971_09_00_00;
+	private $FEBRUARY_15_1971_09_00_00;
+	private $FEBRUARY_16_1971_09_00_00;
+	private $FEBRUARY_17_1971_09_00_00;
+	
+	private $MARCH_05_1971_09_00_00;
+	
+	function __construct( $title = '')
+	{
+		$this->JANUARY_01_1971_09_00_00 = mktime(9,00,00,1,1,1971);
+		$this->JANUARY_01_1971_09_10_00 = mktime(9,10,00,1,1,1971);
+		$this->JANUARY_01_1971_10_00_00 = mktime(10,00,00,1,1,1971);
+		$this->JANUARY_01_1971_10_10_00 = mktime(10,10,00,1,1,1971);
+		$this->JANUARY_01_1971_11_00_00 = mktime(11,00,00,1,1,1971);
+		$this->JANUARY_01_1971_12_00_00 = mktime(12,00,00,1,1,1971);
+		$this->JANUARY_01_1971_12_10_00 = mktime(12,10,00,1,1,1971);
+		
+		$this->JANUARY_02_1971_09_00_00 = mktime(9,00,00,1,2,1971);
+		$this->JANUARY_02_1971_09_10_00 = mktime(9,10,00,1,2,1971);
+		$this->JANUARY_02_1971_12_10_00 = mktime(12,10,00,1,2,1971);
+		
+		$this->JANUARY_03_1971_12_10_00 = mktime(12,10,00,1,3,1971);
+		
+		$this->JANUARY_04_1971_09_00_00 = mktime(9,00,00,1,4,1971);
+		$this->JANUARY_04_1971_09_10_00 = mktime(9,10,00,1,4,1971);
+		$this->JANUARY_04_1971_12_10_00 = mktime(12,10,00,1,4,1971);
+		
+		$this->JANUARY_05_1971_09_00_00 = mktime(9,00,00,1,5,1971);
+		$this->JANUARY_05_1971_09_10_00 = mktime(9,10,00,1,5,1971);
+		$this->JANUARY_05_1971_12_00_00 = mktime(12,00,00,1,5,1971);
+		
+		$this->JANUARY_08_1971_09_00_00 = mktime(9,00,00,1,8,1971);
+		$this->JANUARY_08_1971_09_10_00 = mktime(9,10,00,1,8,1971);
+		
+		$this->JANUARY_09_1971_09_00_00 = mktime(9,00,00,1,9,1971);
+		$this->JANUARY_09_1971_09_10_00 = mktime(9,10,00,1,9,1971);
+		
+		$this->JANUARY_11_1971_09_00_00 = mktime(9,00,00,1,11,1971);
+		$this->JANUARY_11_1971_09_10_00 = mktime(9,10,00,1,11,1971);
+		
+		$this->JANUARY_12_1971_09_00_00 = mktime(9,00,00,1,12,1971);
+		$this->JANUARY_18_1971_09_00_00 = mktime(9,00,00,1,18,1971);
+		$this->JANUARY_19_1971_09_00_00 = mktime(9,00,00,1,19,1971);
+		
+		$this->JANUARY_25_1971_09_00_00 = mktime(9,00,00,1,25,1971);
+		$this->JANUARY_26_1971_09_00_00 = mktime(9,00,00,1,26,1971);
+
+		$this->FEBRUARY_01_1971_09_00_00 = mktime(9,00,00,2,1,1971);	
+		$this->FEBRUARY_02_1971_09_00_00 = mktime(9,00,00,2,2,1971);	
+		$this->FEBRUARY_03_1971_09_00_00 = mktime(9,00,00,2,3,1971);	
+		$this->FEBRUARY_03_1971_12_10_00 = mktime(12,10,00,2,3,1971);	
+		$this->FEBRUARY_04_1971_09_00_00 = mktime(9,00,00,2,4,1971);	
+		$this->FEBRUARY_04_1971_12_10_00 = mktime(12,10,00,2,4,1971);	
+		$this->FEBRUARY_05_1971_09_00_00 = mktime(9,00,00,2,5,1971);	
+		$this->FEBRUARY_08_1971_09_00_00 = mktime(9,00,00,2,8,1971);	
+		$this->FEBRUARY_15_1971_09_00_00 = mktime(9,00,00,2,15,1971);	
+		$this->FEBRUARY_16_1971_09_00_00 = mktime(9,00,00,2,16,1971);	
+		$this->FEBRUARY_17_1971_09_00_00 = mktime(9,00,00,2,17,1971);	
+		
+		$this->MARCH_05_1971_09_00_00 = mktime(9,00,00,3,5,1971);
+
+		parent::__construct( $title );
+	}
+	
+	/*
+	 * Tests forbidden call to setHour on Piwik_ScheduledTime_Hourly
+	 */
+	public function test_setHour_ScheduledTime_Hourly()
+	{
+		try {
+			$hourlySchedule = new Piwik_ScheduledTime_Hourly();
+			$hourlySchedule->setHour(0);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+
+	/*
+	 * Tests invalid call to setHour on Piwik_ScheduledTime_Daily
+	 */
+	public function test_setHour_ScheduledTime_Daily_Negative()
+	{
+		try {
+			$dailySchedule = new Piwik_ScheduledTime_Daily();
+			$dailySchedule->setHour(-1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+
+	/*
+	 * Tests invalid call to setHour on Piwik_ScheduledTime_Daily
+	 */
+	public function test_setHour_ScheduledTime_Daily_Over_24()
+	{
+		try {
+			$dailySchedule = new Piwik_ScheduledTime_Daily();
+			$dailySchedule->setHour(25);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests invalid call to setHour on Piwik_ScheduledTime_Weekly
+	 */
+	public function test_setHour_ScheduledTime_Weekly_Negative()
+	{
+		try {
+			$weeklySchedule = new Piwik_ScheduledTime_Weekly();
+			$weeklySchedule->setHour(-1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+
+	/*
+	 * Tests invalid call to setHour on Piwik_ScheduledTime_Weekly
+	 */
+	public function test_setHour_ScheduledTime_Weekly_Over_24()
+	{
+		try {
+			$weeklySchedule = new Piwik_ScheduledTime_Weekly();
+			$weeklySchedule->setHour(25);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests invalid call to setHour on Piwik_ScheduledTime_Monthly
+	 */
+	public function test_setHour_ScheduledTime_Monthly_Negative()
+	{
+		try {
+			$monthlySchedule = new Piwik_ScheduledTime_Monthly();
+			$monthlySchedule->setHour(-1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+
+	/*
+	 * Tests invalid call to setHour on Piwik_ScheduledTime_Monthly
+	 */
+	public function test_setHour_ScheduledTime_Monthly_Over_24()
+	{
+		try {
+			$monthlySchedule = new Piwik_ScheduledTime_Monthly();
+			$monthlySchedule->setHour(25);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}	
+
+	/*
+	 * Tests forbidden call to setDay on Piwik_ScheduledTime_Hourly
+	 */
+	public function test_setDay_ScheduledTime_Hourly()
+	{
+		try {
+			$hourlySchedule = new Piwik_ScheduledTime_Hourly();
+			$hourlySchedule->setDay(1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests forbidden call to setDay on Piwik_ScheduledTime_Daily
+	 */
+	public function test_setDay_ScheduledTime_Daily()
+	{
+		try {
+			$dailySchedule = new Piwik_ScheduledTime_Daily();
+			$dailySchedule->setDay(1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests invalid call to setDay on Piwik_ScheduledTime_Weekly
+	 */
+	public function test_setDay_ScheduledTime_Weekly_Day_0()
+	{
+		try {
+			$weeklySchedule = new Piwik_ScheduledTime_Weekly();
+			$weeklySchedule->setDay(0);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+
+	/*
+	 * Tests invalid call to setDay on Piwik_ScheduledTime_Weekly
+	 */
+	public function test_setDay_ScheduledTime_Weekly_Over_7()
+	{
+		try {
+			$weeklySchedule = new Piwik_ScheduledTime_Weekly();
+			$weeklySchedule->setDay(8);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests invalid call to setDay on Piwik_ScheduledTime_Monthly
+	 */
+	public function test_setDay_ScheduledTime_Monthly_Day_0()
+	{
+		try {
+			$monthlySchedule = new Piwik_ScheduledTime_Monthly();
+			$monthlySchedule->setDay(0);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+
+	/*
+	 * Tests invalid call to setDay on Piwik_ScheduledTime_Monthly
+	 */
+	public function test_setDay_ScheduledTime_Monthly_Over_7()
+	{
+		try {
+			$monthlySchedule = new Piwik_ScheduledTime_Monthly();
+			$monthlySchedule->setDay(8);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests forbidden call to setWeek on Piwik_ScheduledTime_Hourly
+	 */
+	public function test_setWeek_ScheduledTime_Hourly()
+	{
+		try {
+			$hourlySchedule = new Piwik_ScheduledTime_Hourly();
+			$hourlySchedule->setWeek(1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests forbidden call to setWeek on Piwik_ScheduledTime_Daily
+	 */
+	public function test_setWeek_ScheduledTime_Daily()
+	{
+		try {
+			$dailySchedule = new Piwik_ScheduledTime_Daily();
+			$dailySchedule->setWeek(1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+	
+	/*
+	 * Tests forbidden call to setWeek on Piwik_ScheduledTime_Weekly
+	 */
+	public function test_setWeek_ScheduledTime_Weekly()
+	{
+		try {
+			$weeklySchedule = new Piwik_ScheduledTime_Weekly();
+			$weeklySchedule->setWeek(1);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}	
+	
+	/*
+	 * Tests invalid call to setWeek on Piwik_ScheduledTime_Monthly
+	 */
+	public function test_setWeek_ScheduledTime_Monthly_Week_0()
+	{
+		try {
+			$monthlySchedule = new Piwik_ScheduledTime_Monthly();
+			$monthlySchedule->setWeek(0);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}
+
+	/*
+	 * Tests invalid call to setWeek on Piwik_ScheduledTime_Monthly
+	 */
+	public function test_setWeek_ScheduledTime_Monthly_Over_4()
+	{
+		try {
+			$monthlySchedule = new Piwik_ScheduledTime_Monthly();
+			$monthlySchedule->setWeek(5);
+			$this->fail("Exception not raised.");
+		}
+		catch (Exception $expected) {
+			$this->pass();
+			return;
+		}
+	}	
+	
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Hourly
+	 *
+	 */
+	public function test_getRescheduledTime_Hourly()
+	{
+		
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 1 1971 10:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Hourly_Test();
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_01_1971_10_00_00);
+
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task to simulate a previous task
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 1 1971 10:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Hourly_Test();
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_10_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_01_1971_10_00_00);
+
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 1 hour and 10 minutes after the cron task to simulate a long previous task
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 1 1971 11:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Hourly_Test();
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_10_10_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_01_1971_11_00_00);
+	}
+
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Daily with unspecified hour
+	 *
+	 */
+	public function test_getRescheduledTime_Daily_Unspecified_Hour()
+	{
+
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 2 1971 09:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Daily_Test();
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_02_1971_09_00_00);
+
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task to simulate a previous task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 2 1971 09:10:00 GMT
+		 *  The task would then be executed at January 2 1971 10:00:00 which is ok because setHour has not been called
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Daily_Test();
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_10_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_02_1971_09_10_00);
+	}
+
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Daily with specified hour
+	 *
+	 */
+	public function test_getRescheduledTime_Daily_Specified_Hour()
+	{
+
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 2 1971 09:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Daily_Test();
+		$hourlySchedule->setHour(9);
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_02_1971_09_00_00);
+
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task to simulate a previous task
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 2 1971 09:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Daily_Test();
+		$hourlySchedule->setHour(9);
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_10_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_02_1971_09_00_00);
+
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 1 1971 12:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 2 1971 09:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Daily_Test();
+		$hourlySchedule->setHour(9);
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_12_00_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_02_1971_09_00_00);
+
+		/*
+		 * Test 4
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 1 1971 12:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task to simulate a previous task
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 2 1971 09:00:00 GMT
+		 */
+		$hourlySchedule = new Piwik_ScheduledTime_Daily_Test();
+		$hourlySchedule->setHour(9);
+		$hourlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_12_10_00);
+		$this->assertEqual($hourlySchedule->getRescheduledTime(), $this->JANUARY_02_1971_09_00_00);
+	}
+	
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Weekly with unspecified hour and unspecified day
+	 *
+	 */
+	public function test_getRescheduledTime_Weekly_Unspecified_Hour_Unspecified_Day()
+	{
+
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 8 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_08_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task to simulate a previous task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 8 1971 09:10:00 GMT
+		 *  The task would then be executed at January 8 1971 10:00:00 which is ok because setHour has not been called
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_10_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_08_1971_09_10_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 1 day and 10 minutes after the cron task to simulate a long previous task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 9 1971 09:10:00 GMT
+		 *  The task would then be executed at January 9 1971 10:00:00 which is ok because setHour and setDay 
+		 *  have not been called.
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_09_10_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_09_1971_09_10_00);
+
+	}
+	
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Weekly with specified hour and unspecified day
+	 *
+	 */
+	public function test_getRescheduledTime_Weekly_Specified_Hour_Unspecified_Day()
+	{
+
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is not called, no need to control the scheduled day
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 8 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_08_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is not called, no need to control the scheduled day
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 8 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_10_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_08_1971_09_00_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 1 day and 10 minutes after the cron task to simulate a long previous task
+		 *  - setHour is set to 9
+		 *  - setDay is not called, no need to control the scheduled day
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 9 1971 09:00:00 GMT
+		 *  The task would then be executed at January 9 1971 09:00:00 which is ok because setDay 
+		 *  has not been called.
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_09_10_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_09_1971_09_00_00);
+		
+		/*
+		 * Test 4
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 1 1971 12:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is not called, no need to control the scheduled day
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 8 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_12_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_08_1971_09_00_00);
+	}	
+
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Weekly with unspecified hour and specified day
+	 *
+	 */
+	public function test_getRescheduledTime_Weekly_Unspecified_Hour_Specified_Day()
+	{
+
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at Monday January 4 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setDay is set to 1, Monday
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday January 11 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_04_1971_09_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at Monday January 4 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task
+		 *  - setDay is set to 1
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday January 11 1971 09:10:00 GMT
+		 *  The task will run at January 11 1971 10:00:00 GMT which is ok because setHour has not been called
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_04_1971_09_10_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_10_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron fails to run at Monday January 4 1971 09:00:00 GMT, cron restarted at January 5 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setDay is set to 1
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns January 11 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_05_1971_09_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_00_00);
+
+	}
+	
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Weekly with specified hour and specified day
+	 *
+	 */
+	public function test_getRescheduledTime_Weekly_Specified_Hour_Specified_Day()
+	{
+
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at Monday January 4 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setDay is set to 1, Monday
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday January 11 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_04_1971_09_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at Monday January 4 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task
+		 *  - setDay is set to 1, Monday
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday January 11 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_04_1971_09_10_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_00_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron fails to run at Monday January 4 1971 09:00:00 GMT, cron restarted at January 5 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setDay is set to 1, Monday
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday January 11 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_05_1971_09_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_00_00);
+		
+		/*
+		 * Test 4
+		 *
+		 * Context :
+		 *  - Cron fails to run at Monday January 4 1971 09:00:00 GMT, cron restarted at January 5 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task
+		 *  - setDay is set to 1, Monday
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday January 11 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_05_1971_09_10_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_00_00);	
+		
+		/*
+		 * Test 5
+		 *
+		 * Context :
+		 *  - Cron fails to run at Monday January 4 1971 09:00:00 GMT, cron restarted at January 5 1971 12:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setDay is set to 1, Monday
+		 *  - setHour is set to 9
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday January 11 1971 09:00:00 GMT
+		 */
+		$weeklySchedule = new Piwik_ScheduledTime_Weekly_Test();
+		$weeklySchedule->setDay(1);
+		$weeklySchedule->setHour(9);
+		$weeklySchedule->setReturnValue('getTime', $this->JANUARY_05_1971_12_00_00);
+		$this->assertEqual($weeklySchedule->getRescheduledTime(), $this->JANUARY_11_1971_09_00_00);	
+	}
+	
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Monthly with unspecified hour, unspecified day and unspecified week
+	 *
+	 */
+	public function test_getRescheduledTime_Monthly_Unspecified_Hour_Unspecified_Day_Unspecified_Week()
+	{
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is not called, no need to control the scheduled week
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 1 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_01_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at January 5 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is not called, no need to control the scheduled week
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 5 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_05_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_05_1971_09_00_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron runs at February 5 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is not called, no need to control the scheduled week
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns March 5 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setReturnValue('getTime', $this->FEBRUARY_05_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->MARCH_05_1971_09_00_00);
+	}
+	
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Monthly with unspecified hour, unspecified day and specified week
+	 *
+	 */
+	public function test_getRescheduledTime_Monthly_Unspecified_Hour_Unspecified_Day_Specified_Week()
+	{
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday February 1 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_01_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, cron restarts at January 3 1971 12:00:00 GMT
+		 *  - getRescheduledTime is called 10 minutes after the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 3 1971 12:10:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_03_1971_12_10_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_03_1971_12_10_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, cron restarts at January 4 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday February 4 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_04_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_04_1971_09_00_00);
+		
+		/*
+		 * Test 4
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, cron restarts at January 11 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 4 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_11_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_04_1971_09_00_00);
+		
+		/*
+		 * Test 5
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, cron restarts at January 18 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 4 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_18_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_04_1971_09_00_00);
+		
+		/*
+		 * Test 6
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, cron restarts at January 25 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 4 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_25_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_04_1971_09_00_00);
+		
+		/*
+		 * Test 7
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, cron restarts at January 26 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 5 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_26_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_05_1971_09_00_00);
+		
+		/*
+		 * Test 8
+		 *
+		 * Context :
+		 *  - Cron to runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is not called, no need to control the scheduled day
+		 *  - setWeek is set to 2
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns February 8 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setWeek(2);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_08_1971_09_00_00);
+	}
+	
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Monthly with unspecified hour, specified day and unspecified week
+	 *
+	 */
+	public function test_getRescheduledTime_Monthly_Unspecified_Hour_Specified_Day_Unspecified_Week()
+	{
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron runs at January 1 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is set to 1
+		 *  - setWeek is not called, no need to control the scheduled week
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday February 1 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setDay(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_01_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_01_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron runs at Saturday January 2 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is set to 2
+		 *  - setWeek is not called, no need to control the scheduled week
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Tuesday February 2 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setDay(2);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_02_1971_09_00_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron runs at Saturday January 2 1971 09:00:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is not called, no need to control the scheduled hour
+		 *  - setDay is set to 3
+		 *  - setWeek is not called, no need to control the scheduled week
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Wednesday February 3 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setDay(3);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_09_00_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_03_1971_09_00_00);
+	}
+
+	/*
+	 * Tests getRescheduledTime on Piwik_ScheduledTime_Monthly with specified hour, specified day and specified week
+	 *
+	 */
+	public function test_getRescheduledTime_Monthly_Specified_Hour_Specified_Day_Specified_Week()
+	{
+		/*
+		 * Test 1
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 2 1971 12:10:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is set to 1
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday February 1 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setHour(9);
+		$monthlySchedule->setDay(1);
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_12_10_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_01_1971_09_00_00);
+		
+		/*
+		 * Test 2
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 2 1971 12:10:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is set to 2
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Tuesday February 2 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setHour(9);
+		$monthlySchedule->setDay(2);
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_12_10_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_02_1971_09_00_00);
+		
+		/*
+		 * Test 3
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 2 1971 12:10:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is set to 3
+		 *  - setWeek is set to 1
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Wednesday February 3 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setHour(9);
+		$monthlySchedule->setDay(3);
+		$monthlySchedule->setWeek(1);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_12_10_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_03_1971_09_00_00);
+		
+		/*
+		 * Test 4
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 2 1971 12:10:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is set to 1
+		 *  - setWeek is set to 3
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Monday February 15 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setHour(9);
+		$monthlySchedule->setDay(1);
+		$monthlySchedule->setWeek(3);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_12_10_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_15_1971_09_00_00);
+		
+		/*
+		 * Test 5
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 2 1971 12:10:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is set to 2
+		 *  - setWeek is set to 3
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Tuesday February 16 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setHour(9);
+		$monthlySchedule->setDay(2);
+		$monthlySchedule->setWeek(3);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_12_10_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_16_1971_09_00_00);
+		
+		/*
+		 * Test 6
+		 *
+		 * Context :
+		 *  - Cron fails to run at January 1 1971 09:00:00 GMT, runs at January 2 1971 12:10:00 GMT
+		 *  - getRescheduledTime is called within the same second as the cron task
+		 *  - setHour is set to 9
+		 *  - setDay is set to 3
+		 *  - setWeek is set to 3
+		 *
+		 * Expected :
+		 *  getRescheduledTime returns Wednesday February 17 1971 09:00:00 GMT
+		 */
+		$monthlySchedule = new Piwik_ScheduledTime_Monthly_Test();
+		$monthlySchedule->setHour(9);
+		$monthlySchedule->setDay(3);
+		$monthlySchedule->setWeek(3);
+		$monthlySchedule->setReturnValue('getTime', $this->JANUARY_02_1971_12_10_00);
+		$this->assertEqual($monthlySchedule->getRescheduledTime(), $this->FEBRUARY_17_1971_09_00_00);
+	}
+}
\ No newline at end of file
Index: plugins/CoreAdminHome/API.php
===================================================================
--- plugins/CoreAdminHome/API.php	(revision 0)
+++ plugins/CoreAdminHome/API.php	(revision 0)
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: API.php 2519 2010-07-16 19:51:11Z SteveG $
+ * 
+ * @category Piwik_Plugins
+ * @package Piwik_CoreAdminHome
+ */
+
+/**
+ *
+ * @package Piwik_CoreAdminHome
+ */
+class Piwik_CoreAdminHome_API 
+{
+	static private $instance = null;
+	static public function getInstance()
+	{
+		if (self::$instance == null)
+		{
+			$c = __CLASS__;
+			self::$instance = new $c();
+		}
+		return self::$instance;
+	}
+
+	public function runScheduledTime ( )
+	{
+		Piwik::checkUserIsSuperUser();
+		Piwik_TaskScheduler::runTasks();
+		return true;
+	}
+}
Index: plugins/CoreAdminHome/CoreAdminHome.php
===================================================================
--- plugins/CoreAdminHome/CoreAdminHome.php	(revision 2548)
+++ plugins/CoreAdminHome/CoreAdminHome.php	(working copy)
@@ -31,10 +31,21 @@
 		return array( 
 			'AssetManager.getCssFiles' => 'getCssFiles',
 			'AssetManager.getJsFiles' => 'getJsFiles',
-			'AdminMenu.add' => 'addMenu'
+			'AdminMenu.add' => 'addMenu',
+			'TaskScheduler.getScheduledTasks' => 'getScheduledTasks',
 		);
 	}
 	
+	function getScheduledTasks ( $notification )
+	{
+		$tasks = &$notification->getNotificationObject();
+		
+		$optimizeArchiveTableTask = new Piwik_ScheduledTask ( 'Piwik_CoreAdminHome',
+															'optimizeArchiveTable',
+															new Piwik_ScheduledTime_Monthly() );
+		$tasks[] = $optimizeArchiveTableTask;
+	}
+	
 	function getCssFiles( $notification )
 	{
 		$cssFiles = &$notification->getNotificationObject();
@@ -68,4 +79,16 @@
 							Piwik::isUserIsSuperUser(),
 							$order = 6);
 	}
+	
+	function optimizeArchiveTable()
+	{
+		$tablesPiwik = Piwik::getTablesInstalled();
+		$archiveTables = array_filter ($tablesPiwik, array("Piwik_CoreAdminHome", "isArchiveTable"));
+		Piwik_Exec("OPTIMIZE TABLE " . implode(",", $archiveTables) );
+	}
+	
+	private function isArchiveTable ( $tableName )
+	{
+		return preg_match ( '/piwik_archive_/', $tableName ) > 0;
+	}
 }
Index: misc/cron/archive.sh
===================================================================
--- misc/cron/archive.sh	(revision 2548)
+++ misc/cron/archive.sh	(working copy)
@@ -2,6 +2,8 @@
 
 # Description
 # This cron script will automatically run Piwik archiving every hour.
+# The script will also run scheduled tasks configured within piwik using 
+# the event hook 'TaskScheduler.getScheduledTasks'
 
 # It automatically fetches the Super User token_auth 
 # and triggers the archiving for all websites for all periods.
@@ -80,3 +82,7 @@
 
 echo "Piwik archiving finished."
 
+echo "Starting TaskScheduler..."
+	CMD="$PHP_BIN -q $PIWIK_PATH -- module=API&method=CoreAdminHome.runScheduledTime&token_auth=$TOKEN_AUTH";
+	$CMD
+echo "Piwik TaskScheduler finished."
Index: core/TaskScheduler.php
===================================================================
--- core/TaskScheduler.php	(revision 0)
+++ core/TaskScheduler.php	(revision 0)
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: TaskScheduler.php
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Piwik_TaskScheduler is the class used to manage the execution of periodicaly planned task.
+ * 
+ * It performs the following actions :
+ * 	- Identifies tasks of Piwik
+ *  - Runs tasks
+ *
+ * @package Piwik
+ */
+
+class Piwik_TaskScheduler
+{
+	const GET_TASKS_EVENT = "TaskScheduler.getScheduledTasks";
+	const TIMETABLE_OPTION_STRING = "TaskScheduler.timetable";
+	
+	/*
+	 * runTasks collects tasks defined within piwik plugins, runs them if they are scheduled and reschedules
+	 * the tasks that have been executed.
+	 */
+	static public function runTasks()
+	{
+		// Gets the array where rescheduled timetables are stored
+		$timetable = unserialize(Piwik_GetOption(self::TIMETABLE_OPTION_STRING));
+		
+		// Collects tasks
+		Piwik_PostEvent(self::GET_TASKS_EVENT, $tasks);
+
+		// Loop through each task
+		foreach ($tasks as $task)
+		{
+			$scheduledTime = $task->getScheduledTime();
+			$className = $task->getClassName();
+			$methodName = $task->getMethodName();
+
+			$fullyQualifiedMethodName = $className . '.' . $methodName;
+			
+			$rescheduledTime = $timetable[$fullyQualifiedMethodName];
+			
+			/*
+			 * Task has to be executed if :
+			 * 	- it is the first time, ie. rescheduledTime is not set
+			 *  - that task has already been executed and the current system time is greater than the
+			 *    rescheduled time.
+			 */
+			if ( !isset($rescheduledTime) || (isset($rescheduledTime) && time() >= $rescheduledTime) )
+			{
+				// Updates the rescheduled time
+				$timetable[$fullyQualifiedMethodName] = $scheduledTime->getRescheduledTime();
+				Piwik_SetOption(self::TIMETABLE_OPTION_STRING, serialize($timetable));
+
+				// Run the task
+				call_user_func ( array($className,$methodName) );
+			}
+		}
+	}
+}
\ No newline at end of file
Index: core/ScheduledTime/Daily.php
===================================================================
--- core/ScheduledTime/Daily.php	(revision 0)
+++ core/ScheduledTime/Daily.php	(revision 0)
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: Daily.php
+ * 
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Piwik_ScheduledTime_Daily class is used to schedule tasks every day.
+ *
+ * @see Piwik_ScheduledTask
+ * @package Piwik
+ * @subpackage Piwik_ScheduledTime
+ */
+class Piwik_ScheduledTime_Daily extends Piwik_ScheduledTime
+{	
+	public function getRescheduledTime()
+	{
+		$currentTime = $this->getTime();
+		
+		// Add one day
+		$rescheduledTime = mktime ( 	date('H', $currentTime), 
+									date('i', $currentTime),
+									date('s', $currentTime),
+									date('n', $currentTime),
+									date('j', $currentTime) + 1,
+									date('Y', $currentTime)
+									);
+
+		// Adjusts the scheduled hour
+		$rescheduledTime = $this->adjustHour($rescheduledTime);
+
+		return $rescheduledTime;
+	}
+	
+	public function setDay($_day)
+	{
+		throw new Exception ("Method not supported");
+	}
+	
+	public function setWeek($_week)
+	{
+		throw new Exception ("Method not supported");
+	}
+}
Index: core/ScheduledTime/Hourly.php
===================================================================
--- core/ScheduledTime/Hourly.php	(revision 0)
+++ core/ScheduledTime/Hourly.php	(revision 0)
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: Hourly.php
+ * 
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Piwik_ScheduledTime_Hourly class is used to schedule tasks every hour.
+ *
+ * @see Piwik_ScheduledTask
+ * @package Piwik
+ * @subpackage Piwik_ScheduledTime
+ */
+class Piwik_ScheduledTime_Hourly extends Piwik_ScheduledTime
+{
+	public function getRescheduledTime()
+	{
+		$currentTime = $this->getTime();
+		
+		// Adds one hour and reset the number of minutes
+		$rescheduledTime = mktime ( 	date('H', $currentTime) + 1, 
+									0, 
+									date('s', $currentTime),
+									date('n', $currentTime),
+									date('j', $currentTime),
+									date('Y', $currentTime)
+									);
+		return $rescheduledTime;
+	}
+
+	public function setHour($_hour)
+	{
+		throw new Exception ("Method not supported");
+	}
+	
+	public function setDay($_day)
+	{
+		throw new Exception ("Method not supported");
+	}
+	
+	public function setWeek($_week)
+	{
+		throw new Exception ("Method not supported");
+	}
+	
+}
Index: core/ScheduledTime/Monthly.php
===================================================================
--- core/ScheduledTime/Monthly.php	(revision 0)
+++ core/ScheduledTime/Monthly.php	(revision 0)
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: Monthly.php
+ * 
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Piwik_ScheduledTime_Monthly class is used to schedule tasks every month.
+ *
+ * @see Piwik_ScheduledTask
+ * @package Piwik
+ * @subpackage Piwik_ScheduledTime
+ */
+class Piwik_ScheduledTime_Monthly extends Piwik_ScheduledTime
+{
+	
+	public function getRescheduledTime()
+	{
+		$currentTime = $this->getTime();
+		
+		// Adds one month
+		$rescheduledTime = mktime ( 	date('H', $currentTime), 
+									date('i', $currentTime), 
+									date('s', $currentTime),
+									date('n', $currentTime) + 1,
+									date('j', $currentTime),
+									date('Y', $currentTime)
+									);
+									
+		// Adjusts the scheduled hour
+		$rescheduledTime = $this->adjustHour($rescheduledTime);
+		
+		// Adjusts the scheduled day
+		$rescheduledTime = $this->adjustDay($rescheduledTime);
+		
+		if ( $this->week !== null )
+		{
+			// Computes the week number of the scheduled month
+			$rescheduledWeek = date('W', $rescheduledTime) - (4 * (date('n', $rescheduledTime)-1) );
+			$weekError = $rescheduledWeek - $this->week;
+			
+			if ( $weekError != 0)
+			{ 
+				/*
+				 * Adds or remove a multiple of 7 days to adjust the scheduled week to the one specified
+				 * with setWeek()
+				 */
+				$rescheduledTime = mktime ( 	date('H', $rescheduledTime), 
+											date('i', $rescheduledTime), 
+											date('s', $rescheduledTime),
+											date('n', $rescheduledTime),
+											date('j', $rescheduledTime) - (7 * $weekError),
+											date('Y', $rescheduledTime)
+											);
+			}
+		}
+		
+		return $rescheduledTime;
+	}
+}
Index: core/ScheduledTime/Weekly.php
===================================================================
--- core/ScheduledTime/Weekly.php	(revision 0)
+++ core/ScheduledTime/Weekly.php	(revision 0)
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: Weekly.php
+ * 
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Piwik_ScheduledTime_Weekly class is used to schedule tasks every week.
+ *
+ * @see Piwik_ScheduledTask
+ * @package Piwik
+ * @subpackage Piwik_ScheduledTime
+ */
+class Piwik_ScheduledTime_Weekly extends Piwik_ScheduledTime
+{
+	
+	public function getRescheduledTime()
+	{
+		$currentTime = $this->getTime();
+		
+		// Adds 7 days
+		$rescheduledTime = mktime ( 	date('H', $currentTime), 
+									date('i', $currentTime),
+									date('s', $currentTime),
+									date('n', $currentTime),
+									date('j', $currentTime) + 7,
+									date('Y', $currentTime)
+									);
+		
+		// Adjusts the scheduled hour
+		$rescheduledTime = $this->adjustHour($rescheduledTime);
+		
+		// Adjusts the scheduled day
+		$rescheduledTime = $this->adjustDay($rescheduledTime);
+		
+		return $rescheduledTime;
+	}
+	
+	public function setWeek($_week)
+	{
+		throw new Exception ("Method not supported");
+	}
+}
Index: core/ScheduledTime.php
===================================================================
--- core/ScheduledTime.php	(revision 0)
+++ core/ScheduledTime.php	(revision 0)
@@ -0,0 +1,147 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: ScheduledTime.php
+ * 
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * The Piwik_ScheduledTime abstract class is used as a base class for different types of scheduling intervals.
+ * Piwik_ScheduledTime subclasses are used to schedule tasks within Piwik.
+ *
+ * @see Piwik_ScheduledTask
+ * @package Piwik
+ * @subpackage Piwik_ScheduledTime
+ */
+abstract class Piwik_ScheduledTime
+{
+
+#
+	/**
+	 * @link http://php.net/manual/en/function.date.php, format string : 'G'
+	 * @var integer 
+	 */
+	var $hour;
+	
+	/**
+	 * @link http://php.net/manual/en/function.date.php, format string : 'N'
+	 * @var integer
+	 */
+	var $day;
+	
+	/**
+	 * Represents week number within a month (1 to 4)
+	 * @var integer
+	 */
+	var $week;
+
+	/*
+	 * Returns the system time used by subclasses to compute schedulings.
+	 * This method has been introduced so unit tests can override the current system time.
+	 */
+	protected function getTime()
+	{
+		return time();
+	}
+
+	/**
+	 * Computes the next scheduled time based on the system time at which the method has been called and
+	 * the underlying scheduling interval.
+	 *
+	 * @abstract
+	 * @return integer Returns the rescheduled time measured in the number of seconds since the Unix Epoch
+	 */
+	abstract public function getRescheduledTime();
+
+	/*
+	 * @param  _hour the hour to set, has to be >= 0 and < 24
+	 * @throws Exception if method not supported by subclass or parameter _hour is invalid
+	 */
+	public function setHour($_hour)
+	{
+		if (!($_hour >=0 && $_hour < 24))
+		{			
+			throw new Exception ("Invalid hour parameter, must be >=0 and < 24");
+		}
+
+		$this->hour = $_hour;
+	}
+	
+	/*
+	 * @param  _day the day to set, has to be >= 1 and < 8
+	 * @throws Exception if method not supported by subclass or parameter _hour is invalid
+	 */
+	public function setDay($_day)
+	{
+		if (!($_day >=1 && $_day < 8))
+		{
+			throw new Exception ("Invalid day parameter, must be >=1 and < 8");
+		}
+
+		$this->day = $_day;
+	}
+	
+	/*
+	 * @param  _week the week to set, has to be >= 1 and < 5
+	 * @throws Exception if method not supported by subclass or parameter _week is invalid
+	 */
+	public function setWeek($_week)
+	{
+		if (!($_week >=1 && $_week < 5))
+		{
+			throw new Exception ("Invalid day parameter, must be >=1 and < 5");
+		}
+
+		$this->week = $_week;
+	}	
+	
+	/*
+	 * Computes the delta in seconds needed to adjust the rescheduled time to the required hour.
+	 * 
+	 * @param rescheduledTime The rescheduled time to be adjusted
+	 * @return adjusted rescheduled time
+	 */	
+	protected function adjustHour ($rescheduledTime)
+	{
+		if ( $this->hour !== null )
+		{
+			// Reset the number of minutes and set the scheduled hour to the one specified with setHour()
+			$rescheduledTime = mktime ( 	$this->hour,
+										0,
+										date('s', $rescheduledTime),
+										date('n', $rescheduledTime),
+										date('j', $rescheduledTime),
+										date('Y', $rescheduledTime)
+										);
+		}
+		return $rescheduledTime;
+	}
+	
+	/*
+	 * Computes the delta in seconds needed to adjust the rescheduled time to the required day.
+	 * 
+	 * @param rescheduledTime The rescheduled time to be adjusted
+	 * @return adjusted rescheduled time
+	 */	
+	protected function adjustDay ($rescheduledTime)
+	{
+		if ( $this->day !== null )
+		{
+			// Removes or adds a umber of day to set the scheduled day to the one specified with setDay()
+			$rescheduledTime = mktime ( 	date('H', $rescheduledTime), 
+										date('i', $rescheduledTime),
+										date('s', $rescheduledTime),
+										date('n', $rescheduledTime),
+										date('j', $rescheduledTime) - (date('N', $rescheduledTime) - $this->day),
+										date('Y', $rescheduledTime)
+										);
+		}
+		
+		return $rescheduledTime;
+	}
+}
Index: core/ScheduledTask.php
===================================================================
--- core/ScheduledTask.php	(revision 0)
+++ core/ScheduledTask.php	(revision 0)
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: ScheduledTask.php
+ * 
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Piwik_ScheduledTask is used by the task scheduler and by plugins to configure runnable tasks.
+ * 
+ * @package Piwik
+ * @subpackage Piwik_ScheduledTask
+ */
+class Piwik_ScheduledTask
+{
+    /**
+     * Class name where the specified method is located
+     * @var string 
+     */
+	var $className;
+#
+    /**
+     * Class method to run when task is scheduled
+     * @var string 
+     */
+	var $methodName;
+	
+    /**
+     * The scheduled time policy
+     * @var Piwik_ScheduledTime
+     */
+	var $scheduledTime;
+
+	function __construct( $_className, $_methodName, $_scheduledTime)
+	{
+		$this->className = $_className;
+		$this->methodName = $_methodName;
+		$this->scheduledTime = $_scheduledTime;
+	}
+	
+	/*
+	 * Returns class name
+	 * @return string
+	 */
+	public function getClassName()
+	{
+		return $this->className;
+	}
+
+	/*
+	 * Returns method name
+	 * @return string
+	 */
+	public function getMethodName()
+	{
+		return $this->methodName;
+	}
+
+	/*
+	 * Returns scheduled time
+	 * @return Piwik_ScheduledTime
+	 */
+	public function getScheduledTime()
+	{
+		return $this->scheduledTime;
+	}
+}

