Skip to content

Commit

Permalink
Implemented fluentscheduler#227
Browse files Browse the repository at this point in the history
  • Loading branch information
VitorCioletti committed Feb 25, 2019
1 parent 26ee40a commit e9bb639
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
namespace FluentScheduler.UnitTests
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class ExceptionUnitTests
{
[TestMethod]
public void Except()
{
// Arrange
var now = new DateTime(2019, 2, 25);
var expected = new DateTime(2019, 2, 27);
var exceptionalDays = new DayOfWeek[2]
{
DayOfWeek.Monday,
DayOfWeek.Tuesday,
};

var fluentCalculator = new FluentTimeCalculator();
var calculator = (ITimeCalculator)fluentCalculator;
var run = new ExceptionUnit(fluentCalculator);

// Act
run.Except(exceptionalDays);
var calculated = calculator.Calculate(now);

// Assert
Assert.AreEqual(expected, calculated.Value);
}

[TestMethod]
public void ExceptEmpty()
{
// Arrange
var now = new DateTime(2019, 2, 25);
var expected = new DateTime(2019, 2, 25);
var exceptionalDays = new DayOfWeek[2];

var fluentCalculator = new FluentTimeCalculator();
var calculator = (ITimeCalculator)fluentCalculator;
var run = new ExceptionUnit(fluentCalculator);

// Act
run.Except(exceptionalDays);
var calculated = calculator.Calculate(now);

// Assert
Assert.AreEqual(expected, calculated.Value);
}

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void ExceptEveryDay()
{
// Arrange
var now = new DateTime(2019, 2, 25);
var allDays = new DayOfWeek[7]
{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday,
};

var fluentCalculator = new FluentTimeCalculator();
var calculator = (ITimeCalculator)fluentCalculator;
var run = new ExceptionUnit(fluentCalculator);

// Act / Assert
run.Except(allDays);
calculator.Calculate(now);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
[TestClass]
public class PeriodDurationSetTests
{

[TestMethod]
public void Seconds()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ public void At()
var calculator = (ITimeCalculator)fluentCalculator;
var run = new PeriodOnceSet(fluentCalculator);

var now = DateTime.Now;
var now = new DateTime(2018, 3, 3, 6, 53, 0);
var expected = new DateTime(2018, 3, 3, 8, 40, 0);

calculator.Now = () => now;

// Act
run.At(now.Hour, now.Minute);
run.At(8, 40);
var calculated = calculator.Calculate(now);

// Assert
Assert.AreEqual(now.Hour, calculated.Value.Hour);
Assert.AreEqual(now.Minute, calculated.Value.Minute);
Assert.AreEqual(expected, calculated.Value);
}

[TestMethod]
Expand All @@ -33,16 +35,87 @@ public void AtTimeSpan()
var calculator = (ITimeCalculator)fluentCalculator;
var run = new PeriodOnceSet(fluentCalculator);

var now = DateTime.Now;
var now = new DateTime(2018, 3, 3, 10, 0 ,0);
var timeSpan = new TimeSpan(12, 30, 0);
var expected = new DateTime(2018, 3, 3, 12, 30, 0);

calculator.Now = () => now;

// Act
run.At(timeSpan);
var calculated = calculator.Calculate(now);

// Assert
Assert.AreEqual(timeSpan.Hours, calculated.Value.Hour);
Assert.AreEqual(timeSpan.Minutes, calculated.Value.Minute);
Assert.AreEqual(expected, calculated.Value);
}

[TestMethod]
public void EarlierDateParamsTimeSpan()
{
// Arrange
var now = new DateTime(2019, 2, 8, 3, 0, 0);
var last = new DateTime(2019, 2, 8, 1, 0 ,0);

var time1 = new TimeSpan(5, 0, 0);
var time2 = new TimeSpan(8, 0, 0);
var time3 = new TimeSpan(10, 0, 0);

var expectedFirstRun = new TimeSpan(5, 0, 0);
var expectedSecondRun = new TimeSpan(8, 0, 0);
var expectedThirdRun = new TimeSpan(10, 0, 0);

var fluentCalculator = new FluentTimeCalculator();
var calculator = (ITimeCalculator)fluentCalculator;

calculator.Now = () => now;

var run = new PeriodOnceSet(fluentCalculator);

// Act
var firstRun = run.EarlierDate(last, time1, time2, time3);

// Assert
Assert.AreEqual(expectedFirstRun, firstRun.TimeOfDay);

// Arrange
calculator.Now = () => firstRun;

// Act
var secondRun = run.EarlierDate(firstRun, time1, time2, time3);

// Assert
Assert.AreEqual(expectedSecondRun, secondRun.TimeOfDay);

// Arrange
calculator.Now = () => secondRun;

// Act
var thirdRun = run.EarlierDate(secondRun, time1, time2, time3);

// Assert
Assert.AreEqual(expectedThirdRun, thirdRun.TimeOfDay);
}

[TestMethod]
public void InNextMonth()
{
// Arrange
var now = new DateTime(2019, 02, 11, 0, 30, 0);

var expectedDate = new DateTime(2019, 03, 10, 11, 30, 0);

var fluentCalculator = new FluentTimeCalculator();
var calculator = (ITimeCalculator)fluentCalculator;
var run = new RunSpecifier(fluentCalculator);

calculator.Now = () => now;

// Act
run.Every(1).Months().On(10).At(11, 30);
var calculated = calculator.Calculate(now);

// Assert
Assert.AreEqual(expectedDate, calculated.Value);
}
}
}
33 changes: 33 additions & 0 deletions FluentScheduler/Fluent/3 - Duration/Day/ExceptionUnit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace FluentScheduler
{
using System;
using System.Collections.Generic;
using System.Linq;

public class ExceptionUnit
{
private readonly FluentTimeCalculator _calculator;

internal ExceptionUnit(FluentTimeCalculator calculator) => _calculator = calculator;

/// <summary>
/// Excludes given days from job scheduling.
/// </summary>
/// <param name="exceptionalDays">Days to exclude</param>
public void Except(params DayOfWeek[] exceptionalDays)
{
var allDays = (IEnumerable<DayOfWeek>)Enum.GetValues(typeof(DayOfWeek));

if (allDays.All(day => exceptionalDays.Contains(day)))
throw new ArgumentException($"\"{nameof(exceptionalDays)}\" cannot contain all days of week.");

_calculator.PeriodCalculations.Add(last =>
{
while (exceptionalDays.Contains(last.DayOfWeek))
last = last.AddDays(1);
return last;
});
}
}
}
39 changes: 29 additions & 10 deletions FluentScheduler/Fluent/3 - Duration/PeriodOnceSet.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace FluentScheduler
{
using System;
using System.Collections.Generic;

public class PeriodOnceSet
{
Expand All @@ -13,32 +14,50 @@ public class PeriodOnceSet
/// </summary>
/// <param name="hour">The hours (0 through 23).</param>
/// <param name="minute">The minutes (0 through 59).</param>
public void At(int hour, int minute)
public ExceptionUnit At(int hour, int minute)
{
if (hour < 0 || hour > 23)
throw new ArgumentOutOfRangeException($"\"{nameof(hour)}\" should be in the 0 to 23 range.");

if (minute < 0 || minute > 59)
throw new ArgumentOutOfRangeException($"\"{nameof(minute)}\" should be in the 0 to 59 range.");

_calculator.PeriodCalculations.Add(last => GetEarlierDate(last, new TimeSpan(hour, minute, 0)));
_calculator.PeriodCalculations.Add(last => EarlierDate(last, new TimeSpan(hour, minute, 0)));

return new ExceptionUnit(_calculator);
}

/// <summary>
/// Runs the job at the given time of day.
/// </summary>
/// <param name="time">Time of day</param>
public void At(TimeSpan time) => _calculator.PeriodCalculations.Add(last => GetEarlierDate(last, time));
/// <param name="timeCollection">Time of day</param>
public ExceptionUnit At(params TimeSpan[] timeCollection)
{
_calculator.PeriodCalculations.Add(last => EarlierDate(last, timeCollection));

return new ExceptionUnit(_calculator);
}

private DateTime GetEarlierDate(DateTime last, TimeSpan time)
internal DateTime EarlierDate(DateTime last, params TimeSpan[] timeCollection)
{
var now = DateTime.Now;
var now = ((ITimeCalculator)_calculator).Now();
var calculatedDate = new DateTime();

foreach (var time in timeCollection)
{
var current = new DateTime(now.Year, now.Month, now.Day).Add(time);
var next = new DateTime(last.Year, last.Month, last.Day).Add(time);

if (current.Date < last.Date)
{
calculatedDate = next;
break;
}

var next = new DateTime(last.Year, last.Month, last.Day).Add(time);
calculatedDate = current.TimeOfDay >= now.TimeOfDay ? current : next;
}

return now.TimeOfDay < next.TimeOfDay ?
new DateTime(now.Year, now.Month, now.Day).Add(time) :
next;
return calculatedDate;
}
}
}
17 changes: 16 additions & 1 deletion FluentScheduler/Scheduler/Schedule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public class Schedule
{
internal InternalSchedule Internal { get; private set; }


/// <summary>
/// Creates a new schedule for the given job.
/// </summary>
Expand Down Expand Up @@ -107,6 +106,22 @@ public void SetScheduling(Action<RunSpecifier> specifier)
}
}

/// <summary>
/// Changes the scheduling of this schedule.
/// You must not call this method if the schedule is running.
/// </summary>
/// <param name="cron">Cron of this schedule</param>
public void SetScheduling(string cron)
{
lock (Internal.RunningLock)
{
if (cron == null)
throw new ArgumentNullException(nameof(cron));

Internal.SetScheduling(new CronTimeCalculator(cron));
}
}

/// <summary>
/// Starts the schedule or does nothing if it's already running.
/// </summary>
Expand Down

0 comments on commit e9bb639

Please sign in to comment.