diff --git a/FluentScheduler.UnitTests/Cron/CronTimeCalculatorTests.cs b/FluentScheduler.UnitTests/Cron/CronTimeCalculatorTests.cs index a0b7347..aee9345 100644 --- a/FluentScheduler.UnitTests/Cron/CronTimeCalculatorTests.cs +++ b/FluentScheduler.UnitTests/Cron/CronTimeCalculatorTests.cs @@ -11,8 +11,7 @@ public class CronTimeCalculatorTests public void At0405() { // Arrange - var cronCalculator = new CronTimeCalculator("5 4 * * *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("5 4 * * *"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 22, 4, 5, 0); @@ -28,8 +27,7 @@ public void At0405() public void At0005InAugust() { // Arrange - var cronCalculator = new CronTimeCalculator("5 0 * 8 *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("5 0 * 8 *"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2019, 8, 1, 0, 5, 0); @@ -45,8 +43,7 @@ public void At0005InAugust() public void At0405OnSunday() { // Arrange - var cronCalculator = new CronTimeCalculator("5 4 * * sun"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("5 4 * * sun"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 23, 4, 5, 0); @@ -62,8 +59,7 @@ public void At0405OnSunday() public void At0400OnEveryDayOfMonthFrom8Through14() { // Arrange - var cronCalculator = new CronTimeCalculator("0 4 8-14 * *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("0 4 8-14 * *"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2019, 01, 08, 4, 0, 0); @@ -79,8 +75,7 @@ public void At0400OnEveryDayOfMonthFrom8Through14() public void At1415OnJanuaryFirst() { // Arrange - var cronCalculator = new CronTimeCalculator("15 14 1 * *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("15 14 1 * *"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2019, 1, 1, 14, 15, 0); @@ -96,8 +91,7 @@ public void At1415OnJanuaryFirst() public void At2200OnEveryDayOfWeekFromMondayThroughFriday() { // Arrange - var cronCalculator = new CronTimeCalculator("0 22 * * 1-5"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("0 22 * * 1-5"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 24, 22, 0, 0); @@ -113,8 +107,7 @@ public void At2200OnEveryDayOfWeekFromMondayThroughFriday() public void EveryDayAt0500And1700Hours() { // Arrange - var cronCalculator = new CronTimeCalculator("0 5,17 * * *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("0 5,17 * * *"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 22, 5, 0, 0); @@ -130,8 +123,7 @@ public void EveryDayAt0500And1700Hours() public void AtEveryMinute() { // Arrange - var cronCalculator = new CronTimeCalculator("* * * * *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("* * * * *"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 22, 0, 1, 0); @@ -147,8 +139,7 @@ public void AtEveryMinute() public void AtEvery10Minutes() { // Arrange - var cronCalculator = new CronTimeCalculator("*/10 * * * *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("*/10 * * * *"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 22, 0, 10, 0); @@ -164,8 +155,7 @@ public void AtEvery10Minutes() public void At1700OnSundayAndFriday() { // Arrange - var cronCalculator = new CronTimeCalculator("0 17 * * sun,fri"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("0 17 * * sun,fri"); var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 23, 17, 0, 0); @@ -181,8 +171,7 @@ public void At1700OnSundayAndFriday() public void EverySecond() { // Arrange - var cronCalculator = new CronTimeCalculator("* * * * * *"); - var calculator = (ITimeCalculator)cronCalculator; + var calculator = new CronTimeCalculator("* * * * * *"); var date = new DateTime(2018, 12, 23, 17, 0 , 0); var expected = new DateTime(2018, 12, 23, 17, 0, 1); diff --git a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs index ed1dac0..29b6dab 100644 --- a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs +++ b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs @@ -12,9 +12,8 @@ public void NowAndEvery() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Now().AndEvery(10).Seconds(); @@ -37,9 +36,8 @@ public void EveryTimeSpan() var now = DateTime.Now; var time = new TimeSpan(1, 3, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(time); @@ -56,13 +54,12 @@ public void ExecuteOnlyOnceEverySunday() var date = new DateTime(2020, 9, 1); var expected = new DateTime(2020, 9, 6); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(DayOfWeek.Sunday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -84,13 +81,12 @@ public void ExecuteOnlyOnceEveryMonday() var date = new DateTime(2020, 9, 1); var expected = new DateTime(2020, 9, 7); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(DayOfWeek.Monday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -107,19 +103,17 @@ public void ExecuteOnlyOnceEveryMonday() [Fact] public void ExecuteOnlyOnceEveryTuesday() - { // Arrange var date = new DateTime(2020, 9, 1); var expected = new DateTime(2020, 9, 8); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(DayOfWeek.Tuesday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -141,13 +135,12 @@ public void ExecuteOnlyOnceEveryThursday() var date = new DateTime(2020, 9, 1); var expected = new DateTime(2020, 9, 3); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(DayOfWeek.Thursday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -169,13 +162,12 @@ public void ExecuteOnlyOnceEveryFriday() var date = new DateTime(2020, 9, 1); var expected = new DateTime(2020, 9, 4); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(DayOfWeek.Friday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -197,13 +189,12 @@ public void EverySaturday() var date = new DateTime(2020, 9, 1); var expected = new DateTime(2020, 9, 5); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(DayOfWeek.Saturday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -225,9 +216,8 @@ public void OnceAtAndEvery() var now = DateTime.Now; var at = new DateTime(2000, 10, 10, 10, 10, 10); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.OnceAt(at).AndEvery(10).Seconds(); @@ -249,9 +239,8 @@ public void Now() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Now(); @@ -275,9 +264,8 @@ public void OnceAtHoursMinutes() var hours = 13; var minutes = 50; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.OnceAt(hours, minutes); @@ -300,9 +288,8 @@ public void OnceAtTimeSpan() var now = DateTime.Today; var at = new TimeSpan(13, 50, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.OnceAt(at); @@ -325,9 +312,8 @@ public void OnceAtDateTime() var now = DateTime.Now; var at = new DateTime(2000, 10, 10, 10, 10, 10); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.OnceAt(at); @@ -349,9 +335,8 @@ public void OnceIn() // Arrange var now = DateTime.Today; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.OnceIn(10).Seconds(); @@ -374,9 +359,8 @@ public void OnceInTimeSpan() var now = DateTime.Today; var time = TimeSpan.FromSeconds(10); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.OnceIn(time); @@ -397,11 +381,10 @@ public void EveryWeekday() { // Arrange var now = new DateTime(2020, 9, 2); - var expected = new DateTime(2020, 9, 2); + var expected = new DateTime(2020, 9, 3); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.EveryWeekday(); @@ -410,9 +393,11 @@ public void EveryWeekday() // Assert Equal(expected, calculated); - // Act + // Ac calculated = calculator.Calculate(expected); + expected = new DateTime(2020, 9, 4); + // Assert Equal(expected, calculated); } @@ -421,12 +406,11 @@ public void EveryWeekday() public void EveryWeekend() { // Arrange - var now = new DateTime(2020, 9, 5); - var expected = new DateTime(2020, 9, 5); + var now = new DateTime(2025, 8, 9); + var expected = new DateTime(2025, 8, 10); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.EveryWeekend(); @@ -436,47 +420,49 @@ public void EveryWeekend() Equal(expected, calculated); // Arrange - now = new DateTime(2020, 9, 6); - expected = new DateTime(2020, 9, 6); + now = new DateTime(2025, 8, 10); + expected = new DateTime(2025, 8, 16); // Act calculated = calculator.Calculate(now); // Assert Equal(expected, calculated); + } + [Fact] + public void Everyday() + { // Arrange - now = new DateTime(2020, 9, 7); - expected = new DateTime(2020, 9, 12); + var now = new DateTime(2025, 8, 20, 10, 0, 0); + var expected = new DateTime(2025, 8, 20, 10, 0, 0); + + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); + + calculator.Now = () => now; // Act - calculated = calculator.Calculate(now); + run.Everyday(); + + var calculated = calculator.Calculate(now); // Assert Equal(expected, calculated); - } - [Fact] - public void EveryDay() - { // Arrange - var now = new DateTime(2020, 9, 2, 10, 0, 0); - var expected = new DateTime(2020, 9, 2, 15, 0, 0); - - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + now = expected; + expected = expected.AddDays(1); // Act - run.Every(1).Days().At(15, 0); - var calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated); // Arrange - now = new DateTime(2020, 9, 2, 16, 0, 0); - expected = new DateTime(2020, 9, 3, 15, 0, 0); + now = expected; + expected = expected.AddDays(1); // Act calculated = calculator.Calculate(now); @@ -489,12 +475,11 @@ public void EveryDay() public void EveryMonth() { // Arrange - var now = new DateTime(2020, 9, 2, 10, 0, 0); - var expected = new DateTime(2020, 9, 2, 15, 0, 0); + var now = new DateTime(2025, 8, 2, 10, 0, 0); + var expected = new DateTime(2025, 9, 2, 15, 0, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(1).Months().On(2).At(15, 0); @@ -518,12 +503,11 @@ public void EveryMonth() public void EveryWeek() { // Arrange - var now = new DateTime(2020, 9, 2, 10, 0, 0); - var expected = new DateTime(2020, 9, 2, 15, 0, 0); + var now = new DateTime(2025, 8, 11, 10, 0, 0); + var expected = new DateTime(2025, 8, 18, 15, 0, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(1).Weeks().Between(15, 0, 16, 0); @@ -533,8 +517,8 @@ public void EveryWeek() Equal(expected, calculated); // Arrange - now = new DateTime(2020, 9, 2, 17, 0, 0); - expected = new DateTime(2020, 9, 9, 15, 0, 0); + now = new DateTime(2025, 8, 18, 17, 0, 0); + expected = new DateTime(2025, 8, 25, 15, 0, 0); // Act calculated = calculator.Calculate(now); diff --git a/FluentScheduler.UnitTests/Fluent/2.Once/OnceDurationSetTests.cs b/FluentScheduler.UnitTests/Fluent/2.Once/OnceDurationSetTests.cs index 7fa8d91..78a44de 100644 --- a/FluentScheduler.UnitTests/Fluent/2.Once/OnceDurationSetTests.cs +++ b/FluentScheduler.UnitTests/Fluent/2.Once/OnceDurationSetTests.cs @@ -14,9 +14,8 @@ public void Minutes() var date = new DateTime(2018, 2, 16); var expected = new DateTime(2018, 2, 16, 0, 3, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceDurationSet(3, fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceDurationSet(3, calculator); // Act run.Minutes(); @@ -33,9 +32,8 @@ public void Hours() var date = new DateTime(2018, 2, 16); var expected = new DateTime(2018, 2, 16, 3, 0, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceDurationSet(3, fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceDurationSet(3, calculator); // Act run.Hours(); @@ -52,9 +50,8 @@ public void Days() var date = new DateTime(2018, 2, 16); var expected = new DateTime(2018, 2, 19); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceDurationSet(3, fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceDurationSet(3, calculator); // Act run.Days(); @@ -71,9 +68,8 @@ public void Weeks() var date = new DateTime(2018, 2, 16); var expected = new DateTime(2018, 3, 9); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceDurationSet(3, fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceDurationSet(3, calculator); // Act run.Weeks(); @@ -90,9 +86,8 @@ public void Months() var date = new DateTime(2018, 3, 16); var expected = new DateTime(2018, 6, 16); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceDurationSet(3, fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceDurationSet(3, calculator); // Act run.Months(); diff --git a/FluentScheduler.UnitTests/Fluent/2.Once/OnceSetTests.cs b/FluentScheduler.UnitTests/Fluent/2.Once/OnceSetTests.cs index 355e677..f931c4a 100644 --- a/FluentScheduler.UnitTests/Fluent/2.Once/OnceSetTests.cs +++ b/FluentScheduler.UnitTests/Fluent/2.Once/OnceSetTests.cs @@ -15,9 +15,8 @@ public void AndEveryDayOfWeek() var monday = new DateTime(2018, 2, 19); var sunday = new DateTime(2018, 2, 25); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceSet(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceSet(calculator); // Act run.AndEvery(DayOfWeek.Sunday); @@ -49,9 +48,8 @@ public void EveryInterval() var date = new DateTime(2018, 12, 23); var expected = date.AddSeconds(10); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceSet(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceSet(calculator); // Act run.AndEvery(10).Seconds(); @@ -68,9 +66,8 @@ public void AndEveryWeekday() var date = new DateTime(2018, 12, 22); var expected = new DateTime(2018, 12, 24); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceSet(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceSet(calculator); // Act run.AndEveryWeekday(); @@ -87,9 +84,8 @@ public void AndEveryWeekend() var date = new DateTime(2018, 12, 24); var expected = new DateTime(2018, 12, 29); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new OnceSet(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new OnceSet(calculator); // Act run.AndEveryWeekend(); diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/Day/DayUnitTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/Day/DayUnitTests.cs index 7e3541d..29e473e 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/Day/DayUnitTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/Day/DayUnitTests.cs @@ -15,9 +15,8 @@ public void EveryWeekday() var monday = new DateTime(2018, 02, 19); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new DayUnit(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new DayUnit(calculator); // Act run.Weekday(); @@ -50,9 +49,8 @@ public void EveryWeekend() var now = new DateTime(2018, 02, 13); var expected = new DateTime(2018, 02, 17); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new DayUnit(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new DayUnit(calculator); // Act run.Weekend(); diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs new file mode 100644 index 0000000..c5520cd --- /dev/null +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs @@ -0,0 +1,397 @@ +namespace FluentScheduler.UnitTests; + +using System; +using Xunit; +using static Xunit.Assert; + +public class EverydayUnitTests +{ + [Fact] + public void At() + { + // Arrange + var now = new DateTime(2025, 8, 20, 10, 0, 0); + var expected = new DateTime(2025, 8, 20, 15, 0, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = fluentCalculator; + var run = new EverydayUnit(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.At(15, 0); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(6); + expected = expected.AddDays(1); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + } + + [Fact] + public void AtTimeSpan() + { + // Arrange + var now = new DateTime(2025, 8, 20, 10, 0, 0); + var expected = new DateTime(2025, 8, 20, 15, 0, 0); + + var timeSpan = new TimeSpan(15, 0, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = fluentCalculator; + var run = new EverydayUnit(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.At(timeSpan); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(6); + expected = expected.AddDays(1); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + } + + [Fact] + public void AtMultipleTimeSpan() + { + // Arrange + var timeSpans = new TimeSpan[] { new(15, 0, 0), new(16, 0, 0), new(17, 0, 0) }; + var now = new DateTime(2025, 8, 20, 10, 0, 0); + var expected = new DateTime(2025, 8, 20).Add(timeSpans[0]); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.Everyday().At(timeSpans); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(5.1); + expected = expected.Date.Add(timeSpans[1]); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(1.1); + expected = expected.Date.Add(timeSpans[2]); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(1.1); + expected = new DateTime(2025, 8, 21, 15, 0, 0); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + } + + [Fact] + public void AtMultipleTimeSpan2() + { + // Arrange + var timeSpans = new TimeSpan[] { new(15, 0, 0), new(16, 0, 0), new(17, 0, 0) }; + var now = new DateTime(2025, 8, 20, 15, 1, 0); + var expected = new DateTime(2025, 8, 20).Add(timeSpans[1]); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.Everyday().At(timeSpans); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(1.1); + expected = expected.Date.Add(timeSpans[2]); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(1.1); + expected = new DateTime(2025, 8, 21, 15, 0, 0); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + } + + [Fact] + public void AtMultipleEmptyTimeSpan() + { + var fluentCalculator = new FluentTimeCalculator(); + var run = new EverydayUnit(fluentCalculator); + + // Act Assert + Throws(() => run.At()); + } + + [Fact] + public void AtMultipleNullTimeSpan() + { + // Arrange + var fluentCalculator = new FluentTimeCalculator(); + var run = new EverydayUnit(fluentCalculator); + + // Act Assert + Throws(() => run.At(null)); + } + + [Fact] + public void EverydayAt15() + { + // Arrange + var now = new DateTime(2025, 08, 24, 14, 30, 0); + var expectedDate = new DateTime(2025, 08, 24, 15, 0, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.Everyday().At(15, 0); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + now = expectedDate; + + calculated = calculator.Calculate(expectedDate); + + expectedDate = expectedDate.AddDays(1); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void EverydayAt16() + { + // Arrange + var now = new DateTime(2025, 08, 24, 16, 0, 0); + var expectedDate = new DateTime(2025, 08, 24, 16, 0, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.Everyday().At(16, 0); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + now = expectedDate; + + calculated = calculator.Calculate(expectedDate); + + expectedDate = expectedDate.AddDays(1); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void Between17and19TimeSpan() + { + // Arrange + var now = new DateTime(2025, 08, 24, 16, 30, 0); + var expectedDate = new DateTime(2025, 08, 24, 17, 30, 0); + + var from = new TimeSpan(17, 30, 0); + var to = new TimeSpan(19, 30, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.Everyday().Between(from, to); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void Between21and23TimeSpan() + { + // Arrange + var now = new DateTime(2025, 09, 10, 23, 40, 0); + var expectedDate = new DateTime(2025, 09, 10, 21, 30, 0); + + var from = new TimeSpan(21, 30, 0); + var to = new TimeSpan(23, 30, 0); + + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); + + calculator.Now = () => now; + + // Act + run.Everyday().Between(from, to); + + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void Between23and2TimeSpan() + { + // Arrange + var now = new DateTime(2025, 08, 24, 22, 30, 0); + var expectedDate = new DateTime(2025, 08, 24, 23, 0, 0); + + var from = new TimeSpan(23, 0, 0); + var to = new TimeSpan(2, 0, 0); + + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); + + calculator.Now = () => now; + + // Act + run.Everyday().Between(from, to); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + expectedDate = expectedDate.AddDays(1); + + calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void Between23and2() + { + // Arrange + var now = new DateTime(2025, 08, 24, 22, 30, 0); + var expectedDate = new DateTime(2025, 08, 24, 23, 0, 0); + + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); + + calculator.Now = () => now; + + // Act + run.Everyday().Between(23, 0, 2, 0); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + expectedDate = expectedDate.AddDays(1); + + calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void Between19and22() + { + // Arrange + var now = new DateTime(2025, 08, 24, 20, 0, 0); + var expectedDate = new DateTime(2025, 08, 24, 20, 0, 0); + + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); + + calculator.Now = () => now; + + // Act + run.Everyday().Between(19, 0, 22, 0); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + calculated = calculator.Calculate(expectedDate); + + expectedDate = expectedDate.Date.AddDays(1).Add(new TimeSpan(19, 0, 0)); + + // Assert + Equal(expectedDate, calculated.Value); + + calculated = calculator.Calculate(expectedDate); + + expectedDate = expectedDate.AddDays(1); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void ThrowIfAtEmpty() + { + // Arrange + var fluentCalculator = new FluentTimeCalculator(); + var run = new EverydayUnit(fluentCalculator); + + // Act + Throws(() => run.At()); + } +} \ No newline at end of file diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/Month/MonthUnitTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/Month/MonthUnitTests.cs index 1cffce0..e9d304d 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/Month/MonthUnitTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/Month/MonthUnitTests.cs @@ -13,9 +13,8 @@ public void On() var now = new DateTime(2020, 9, 2); var expected = new DateTime(2020, 9, 2); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var monthUnit = new MonthUnit(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var monthUnit = new MonthUnit(calculator); // Act monthUnit.On(2); diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodDurationSetTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodDurationSetTests.cs index 885c714..d3d5534 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodDurationSetTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodDurationSetTests.cs @@ -12,9 +12,8 @@ public void Seconds() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(5).Seconds(); @@ -30,9 +29,8 @@ public void Minutes() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(5).Minutes(); @@ -48,9 +46,8 @@ public void Hours() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(5).Hours(); @@ -66,9 +63,8 @@ public void Days() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(5).Days(); @@ -84,9 +80,8 @@ public void Weeks() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(5).Weeks(); @@ -102,9 +97,8 @@ public void Months() // Arrange var now = DateTime.Now; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); // Act run.Every(5).Months(); diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs index dfa5022..ac84f5e 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs @@ -13,15 +13,14 @@ public void At() var now = new DateTime(2018, 3, 3, 6, 53, 0); var expected = new DateTime(2018, 3, 3, 8, 40, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new PeriodOnceSet(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new PeriodOnceSet(calculator); calculator.Now = () => now; // Act run.At(8, 40); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -31,140 +30,52 @@ public void At() public void AtTimeSpan() { // Arrange - var now = new DateTime(2018, 3, 3, 10, 0 ,0); + var now = new DateTime(2018, 3, 3, 10, 0, 0); var expected = new DateTime(2018, 3, 3, 12, 30, 0); var timeSpan = new TimeSpan(12, 30, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new PeriodOnceSet(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new PeriodOnceSet(calculator); calculator.Now = () => now; // Act run.At(timeSpan); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); } [Fact] - public void InTheNextMonth() - { - // 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 - Equal(expectedDate, calculated.Value); - } - - [Fact] - public void Between23and2() + public void ThrowIfAtEmpty() { - // Arrange - var now = new DateTime(2019, 08, 19, 23, 30, 0); - var expectedDate = new DateTime(2019, 08, 20, 23, 0, 0); - - var from = new TimeSpan(23, 0, 0); - var to = new TimeSpan(2, 30, 0); - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); - - calculator.Now = () => now; - - // Act - run.Every(1).Days().Between(from, to); - var calculated = calculator.Calculate(now); - - // Assert - Equal(expectedDate, calculated.Value); - } - - [Fact] - public void Between17and19() - { - // Arrange - var now = new DateTime(2019, 08, 19, 16, 30, 0); - var expectedDate = new DateTime(2019, 08, 20, 17, 30, 0); - - var from = new TimeSpan(17, 30, 0); - var to = new TimeSpan(19, 30, 0); - - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); - - calculator.Now = () => now; - - // Act - run.Every(1).Days().Between(from, to); - var calculated = calculator.Calculate(now); - - // Assert - Equal(expectedDate, calculated.Value); - } - - [Fact] - public void Between21and23() - { - // Arrange - var now = new DateTime(2019, 08, 19, 21, 40, 0); - var expectedDate = new DateTime(2019, 08, 20, 21, 40, 0); - - var from = new TimeSpan(21, 30, 0); - var to = new TimeSpan(23, 30, 0); - - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RunSpecifier(fluentCalculator); - - calculator.Now = () => now; + var run = new PeriodOnceSet(fluentCalculator); // Act - run.Every(1).Days().Between(from, to); - var calculated = calculator.Calculate(now); - - // Assert - Equal(expectedDate, calculated.Value); + Throws(() => run.At()); } [Fact] - public void Between19and22() + public void InTheNextMonth() { // Arrange - var now = new DateTime(2019, 08, 19, 23, 50, 0); - var expectedDate = new DateTime(2019, 08, 21, 19, 30, 0); - - var from = new TimeSpan(19, 30, 0); - var to = new TimeSpan(22, 30, 0); + 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); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); calculator.Now = () => now; // Act - run.Every(1).Days().Between(from, to); - var calculated = calculator.Calculate(now); + run.Every(1).Months().On(10).At(11, 30); + var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); } -} +} \ No newline at end of file diff --git a/FluentScheduler.UnitTests/Fluent/4.Restriction/RestrictionUnitTests.cs b/FluentScheduler.UnitTests/Fluent/4.Restriction/RestrictionUnitTests.cs index f0fef3a..30fdb6b 100644 --- a/FluentScheduler.UnitTests/Fluent/4.Restriction/RestrictionUnitTests.cs +++ b/FluentScheduler.UnitTests/Fluent/4.Restriction/RestrictionUnitTests.cs @@ -18,9 +18,8 @@ public void Except() DayOfWeek.Tuesday, }; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RestrictionUnit(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RestrictionUnit(calculator); // Act run.Except(exceptionalDays); @@ -38,9 +37,8 @@ public void ExceptEmpty() var expected = new DateTime(2019, 2, 25); var exceptionalDays = new DayOfWeek[2]; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RestrictionUnit(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RestrictionUnit(calculator); // Act run.Except(exceptionalDays); @@ -66,9 +64,8 @@ public void ExceptEveryDay() DayOfWeek.Saturday, }; - var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; - var run = new RestrictionUnit(fluentCalculator); + var calculator = new FluentTimeCalculator(); + var run = new RestrictionUnit(calculator); // Act / Assert Throws(() => run.Except(allDays)); diff --git a/FluentScheduler.UnitTests/Scheduler/ScheduleTests.cs b/FluentScheduler.UnitTests/Scheduler/ScheduleTests.cs index 97e3eb2..131e7ca 100644 --- a/FluentScheduler.UnitTests/Scheduler/ScheduleTests.cs +++ b/FluentScheduler.UnitTests/Scheduler/ScheduleTests.cs @@ -142,7 +142,7 @@ public async Task SetScheduling() // Arrange var calls = 0; var expectedCalls = 2; - var schedule = new Schedule(() => ++calls, run => run.Now().AndEvery(1).Days()); + var schedule = new Schedule(() => ++calls, run => run.Everyday()); // Act schedule.Start(); diff --git a/FluentScheduler/Common/ThrowHelper.cs b/FluentScheduler/Common/ThrowHelper.cs index e8af5a4..b61ba3c 100644 --- a/FluentScheduler/Common/ThrowHelper.cs +++ b/FluentScheduler/Common/ThrowHelper.cs @@ -4,7 +4,7 @@ namespace FluentScheduler; // helper methods for performing simple validations and that should throw an exception -internal class ThrowHelper +internal static class ThrowHelper { // throws if the given value is not present in the given enum T internal static void ThrowIfNotDefinedInEnum( @@ -35,8 +35,10 @@ internal static void ThrowIfNegative( internal static void ThrowIfOutOfMilitaryTimeRange( int hour, int minute, - [CallerArgumentExpression(nameof(hour))] string hourParamName = null, - [CallerArgumentExpression(nameof(minute))] string minuteParamName = null) + [CallerArgumentExpression(nameof(hour))] + string hourParamName = null, + [CallerArgumentExpression(nameof(minute))] + string minuteParamName = null) { ArgumentOutOfRangeException.ThrowIfNegative(hour, hourParamName); ArgumentOutOfRangeException.ThrowIfNegative(minute, minuteParamName); @@ -63,4 +65,13 @@ internal static void ThrowIfOutOfMilitaryTimeRange( Array.ForEach(values, v => ThrowIfOutOfMilitaryTimeRange(v, paramName)); } -} + + internal static void ThrowIfEmpty( + TimeSpan[] values, [CallerArgumentExpression(nameof(values))] string paramName = null) + { + ArgumentNullException.ThrowIfNull(values); + + if (values.Length == 0) + throw new ArgumentException($"\"{paramName}\" can't be empty."); + } +} \ No newline at end of file diff --git a/FluentScheduler/Cron/CronTimeCalculator.cs b/FluentScheduler/Cron/CronTimeCalculator.cs index adc1f87..3e24b75 100644 --- a/FluentScheduler/Cron/CronTimeCalculator.cs +++ b/FluentScheduler/Cron/CronTimeCalculator.cs @@ -7,10 +7,6 @@ internal class CronTimeCalculator : ITimeCalculator { private readonly CrontabSchedule _calculator; - public void UseUtc() => ((ITimeCalculator)this).Now = () => DateTime.UtcNow; - - Func ITimeCalculator.Now { get; set; } = () => DateTime.Now; - internal CronTimeCalculator(string cronExpression) { var cronFields = cronExpression.Split(StringSeparatorStock.Space, StringSplitOptions.RemoveEmptyEntries).Length; @@ -21,8 +17,12 @@ internal CronTimeCalculator(string cronExpression) _calculator = CrontabSchedule.Parse(cronExpression, parseOptions); } + + public Func Now { get; set; } = () => DateTime.Now; + + public void UseUtc() => ((ITimeCalculator)this).Now = () => DateTime.UtcNow; - DateTime? ITimeCalculator.Calculate(DateTime last) => _calculator.GetNextOccurrence(last); + public DateTime? Calculate(DateTime last) => _calculator.GetNextOccurrence(last); - void ITimeCalculator.Reset() { } + public void Reset() { } } \ No newline at end of file diff --git a/FluentScheduler/Fluent/1.Run/RunSpecifier.cs b/FluentScheduler/Fluent/1.Run/RunSpecifier.cs index f8ff851..693e311 100644 --- a/FluentScheduler/Fluent/1.Run/RunSpecifier.cs +++ b/FluentScheduler/Fluent/1.Run/RunSpecifier.cs @@ -22,6 +22,31 @@ public PeriodDurationSet Every(int interval) return new PeriodDurationSet(interval, _calculator); } + /// + /// Runs the job everyday. Tries to run in the same day if the given time was not reached. + /// + public EverydayUnit Everyday() + { + ITimeCalculator timeCalculator = _calculator; + + var now = timeCalculator.Now(); + var calculatedFirstExecution = false; + + _calculator.PeriodCalculations.Add(last => + { + var next = new DateTime(last.Year, last.Month, last.Day, now.Hour, now.Minute, 0); + + if (calculatedFirstExecution) + next = next.AddDays(1); + + calculatedFirstExecution = true; + + return next; + }); + + return new EverydayUnit(_calculator); + } + /// /// Runs the job according to the given interval. /// @@ -114,7 +139,7 @@ public OnceSet OnceAt(TimeSpan timeOfDay) /// Date and time to run public OnceSet OnceAt(DateTime dateTime) { - _calculator.OnceCalculation = last => dateTime; + _calculator.OnceCalculation = _ => dateTime; return new OnceSet(_calculator); } @@ -141,4 +166,4 @@ public OnceSet OnceIn(TimeSpan delay) _calculator.OnceCalculation = last => last.Add(delay); return new OnceSet(_calculator); } -} +} \ No newline at end of file diff --git a/FluentScheduler/Fluent/3.Duration/Day/DayUnit.cs b/FluentScheduler/Fluent/3.Duration/DayUnit.cs similarity index 89% rename from FluentScheduler/Fluent/3.Duration/Day/DayUnit.cs rename to FluentScheduler/Fluent/3.Duration/DayUnit.cs index bf4089b..7963be7 100644 --- a/FluentScheduler/Fluent/3.Duration/Day/DayUnit.cs +++ b/FluentScheduler/Fluent/3.Duration/DayUnit.cs @@ -1,62 +1,61 @@ -namespace FluentScheduler; - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using static System.DayOfWeek; - -/// -/// The days the job should run -/// -public class DayUnit -{ - private readonly FluentTimeCalculator _calculator; - - internal DayUnit(FluentTimeCalculator calculator) => _calculator = calculator; - - /// - /// Runs the job only on weekdays. - /// - public RestrictionUnit Weekday() - { - _calculator.PeriodCalculations.Add(last => - { - var daysToNextWeekday = 1; - - if (last.DayOfWeek == Friday) - daysToNextWeekday = 3; - - if (last.DayOfWeek == Saturday) - daysToNextWeekday = 2; - - last = last.AddDays(daysToNextWeekday); - - return last; - }); - - return new RestrictionUnit(_calculator); - } - - /// - /// Runs the job only on the weekends. - /// - public RestrictionUnit Weekend() - { - _calculator.PeriodCalculations.Add(last => - { - var daysToNextWeekend = 6 - (int)last.DayOfWeek; - - if (last.DayOfWeek == Saturday) - daysToNextWeekend = 1; - - if (last.DayOfWeek == Sunday) - daysToNextWeekend = 6; - - last = last.AddDays(daysToNextWeekend); - - return last; - }); - - return new RestrictionUnit(_calculator); - } -} +using System; + +namespace FluentScheduler; + +using static DayOfWeek; + +/// +/// The days the job should run +/// +public class DayUnit +{ + private readonly FluentTimeCalculator _calculator; + + internal DayUnit(FluentTimeCalculator calculator) => _calculator = calculator; + + /// + /// Runs the job only on weekdays. + /// + public RestrictionUnit Weekday() + { + _calculator.PeriodCalculations.Add(last => + { + var daysToNextWeekday = 1; + + if (last.DayOfWeek == Friday) + daysToNextWeekday = 3; + + if (last.DayOfWeek == Saturday) + daysToNextWeekday = 2; + + last = last.AddDays(daysToNextWeekday); + + return last; + }); + + return new RestrictionUnit(_calculator); + } + + /// + /// Runs the job only on the weekends. + /// + public RestrictionUnit Weekend() + { + _calculator.PeriodCalculations.Add(last => + { + var daysToNextWeekend = 6 - (int)last.DayOfWeek; + + if (last.DayOfWeek == Saturday) + daysToNextWeekend = 1; + + if (last.DayOfWeek == Sunday) + daysToNextWeekend = 6; + + last = last.AddDays(daysToNextWeekend); + + return last; + }); + + return new RestrictionUnit(_calculator); + } +} diff --git a/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs new file mode 100644 index 0000000..6026799 --- /dev/null +++ b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs @@ -0,0 +1,99 @@ +using System; +using System.Linq; + +namespace FluentScheduler; + +/// +/// The "period" run has been set, but not its unit. +/// +public class EverydayUnit +{ + private readonly FluentTimeCalculator _calculator; + + internal EverydayUnit(FluentTimeCalculator calculator) => _calculator = calculator; + + /// + /// Runs the job at the given time of day (military format). + /// + /// The hour (0 through 23). + /// The minute (0 through 59). + public void At(int hour, int minute) + { + ThrowHelper.ThrowIfOutOfMilitaryTimeRange(hour, minute); + + _calculator.PeriodCalculations.Add(last => + { + ITimeCalculator timeCalculator = _calculator; + var now = timeCalculator.Now(); + + var next = new DateTime(last.Year, last.Month, last.Day, hour, minute, 0); + + return now > next ? next.AddDays(1) : next; + }); + } + + /// + /// Runs the job at the given time of day. + /// + /// Time of day. + public void At(params TimeSpan[] timeCollection) + { + ThrowHelper.ThrowIfEmpty(timeCollection); + ThrowHelper.ThrowIfOutOfMilitaryTimeRange(timeCollection); + + _calculator.PeriodCalculations.Add(_ => + { + ITimeCalculator timeCalculator = _calculator; + var now = timeCalculator.Now(); + + var orderedTimes = timeCollection.Order(); + + var nextTime = orderedTimes.First(); + + nextTime = orderedTimes.FirstOrDefault(t => now.TimeOfDay < t, nextTime); + + var next = new DateTime(now.Year, now.Month, now.Day).Add(nextTime); + + return now > next ? next.AddDays(1) : next; + }); + } + + /// + /// Runs the job at the given period of time. + /// + /// Hour to delimitate period beginning. + /// Minute to delimitade period beginning. + /// Hour to delimitate period end. + /// Minute to delimitade period end. + public void Between(int hourFrom, int minuteFrom, int hourTo, int minuteTo) => + Between(new TimeSpan(hourFrom, minuteFrom, 0), new TimeSpan(hourTo, minuteTo, 0)); + + /// + /// Runs the job at the given period of time. + /// + /// Time of the day to delimitate the period beginnig. + /// Time of the day to delimitade the period end. + public void Between(TimeSpan from, TimeSpan to) + { + if (from == to) + throw new ArgumentException($"The parameters '{nameof(from)}' and '{nameof(to)}' must not be equal."); + + _calculator.PeriodCalculations.Add( + last => + { + var fromDate = new DateTime(last.Year, last.Month, last.Day).Add(from); + var toDate = new DateTime(last.Year, last.Month, last.Day).Add(to); + var now = ((ITimeCalculator)_calculator).Now(); + + var next = new DateTime(last.Year, last.Month, last.Day).Add(from); + + if (now >= fromDate && now <= toDate) + { + next = now; + } + + return next; + } + ); + } +} \ No newline at end of file diff --git a/FluentScheduler/Fluent/3.Duration/Month/MonthUnit.cs b/FluentScheduler/Fluent/3.Duration/MonthUnit.cs similarity index 96% rename from FluentScheduler/Fluent/3.Duration/Month/MonthUnit.cs rename to FluentScheduler/Fluent/3.Duration/MonthUnit.cs index 0fcab3b..f1f7360 100644 --- a/FluentScheduler/Fluent/3.Duration/Month/MonthUnit.cs +++ b/FluentScheduler/Fluent/3.Duration/MonthUnit.cs @@ -1,28 +1,28 @@ -namespace FluentScheduler; - -using System; - -/// -/// The months the job should run -/// -public class MonthUnit -{ - private readonly FluentTimeCalculator _calculator; - - internal MonthUnit(FluentTimeCalculator calculator) => _calculator = calculator; - - /// - /// Runs the job on the given day of the month. - /// - /// The day (1 through the number of days in month) - public RestrictionUnit On(int day) - { - ArgumentOutOfRangeException.ThrowIfNegative(day); - ArgumentOutOfRangeException.ThrowIfGreaterThan(day, 31); - - _calculator.PeriodCalculations.Add( - last => new DateTime(last.Year, last.Month, day, last.Hour, last.Minute, last.Second)); - - return new RestrictionUnit(_calculator); - } -} +namespace FluentScheduler; + +using System; + +/// +/// The months the job should run +/// +public class MonthUnit +{ + private readonly FluentTimeCalculator _calculator; + + internal MonthUnit(FluentTimeCalculator calculator) => _calculator = calculator; + + /// + /// Runs the job on the given day of the month. + /// + /// The day (1 through the number of days in month) + public RestrictionUnit On(int day) + { + ArgumentOutOfRangeException.ThrowIfNegative(day); + ArgumentOutOfRangeException.ThrowIfGreaterThan(day, 31); + + _calculator.PeriodCalculations.Add( + last => new DateTime(last.Year, last.Month, day, last.Hour, last.Minute, last.Second)); + + return new RestrictionUnit(_calculator); + } +} diff --git a/FluentScheduler/Fluent/3.Duration/PeriodDurationSet.cs b/FluentScheduler/Fluent/3.Duration/PeriodDurationSet.cs index 13d8da9..aba45e5 100644 --- a/FluentScheduler/Fluent/3.Duration/PeriodDurationSet.cs +++ b/FluentScheduler/Fluent/3.Duration/PeriodDurationSet.cs @@ -1,3 +1,5 @@ +using System; + namespace FluentScheduler; /// @@ -35,6 +37,9 @@ internal PeriodDurationSet(int duration, FluentTimeCalculator calculator) /// public RestrictionUnit Days() { + if (_duration == 1) + throw new InvalidOperationException($"Use {nameof(RunSpecifier.Everyday)} instead."); + _calculator.PeriodCalculations.Add(last => last.AddDays(_duration)); return new RestrictionUnit(_calculator); } diff --git a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs index 0fa3d6d..ae02d5a 100644 --- a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs +++ b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs @@ -1,3 +1,5 @@ +using System.Globalization; + namespace FluentScheduler; using System; @@ -29,6 +31,7 @@ public void At(int hour, int minute) /// Time of day. public void At(params TimeSpan[] timeCollection) { + ThrowHelper.ThrowIfEmpty(timeCollection); ThrowHelper.ThrowIfOutOfMilitaryTimeRange(timeCollection); foreach (var time in timeCollection) @@ -67,18 +70,9 @@ public void Between(TimeSpan from, TimeSpan to) _calculator.PeriodCalculations.Add( last => { - var now = ((ITimeCalculator)_calculator).Now(); - var lastTime = last.TimeOfDay; - var next = new DateTime(last.Year, last.Month, last.Day).Add(from); - if (from >= to || lastTime < from) - return next; - - if (lastTime > to) - return next.AddDays(1); - - return last; + return next; } ); } diff --git a/FluentScheduler/Fluent/FluentTimeCalculator.cs b/FluentScheduler/Fluent/FluentTimeCalculator.cs index 4316281..78626c9 100644 --- a/FluentScheduler/Fluent/FluentTimeCalculator.cs +++ b/FluentScheduler/Fluent/FluentTimeCalculator.cs @@ -7,21 +7,21 @@ namespace FluentScheduler; internal class FluentTimeCalculator : ITimeCalculator { private bool _firstCalculation = true; + + internal FluentTimeCalculator() { } + + public Func Now { get; set; } = () => DateTime.Now; internal Func OnceCalculation { get; set; } internal IList> PeriodCalculations { get; private set; } = new List>(); - internal FluentTimeCalculator() { } - internal FluentTimeCalculator(Action specifier) => specifier(new RunSpecifier(this)); - void ITimeCalculator.Reset() => _firstCalculation = true; - - Func ITimeCalculator.Now { get; set; } = () => DateTime.Now; + public void Reset() => _firstCalculation = true; - DateTime? ITimeCalculator.Calculate(DateTime last) => CalculateOnce(last) ?? CalculatePeriod(last); + public DateTime? Calculate(DateTime last) => CalculateOnce(last) ?? CalculatePeriod(last); private DateTime? CalculateOnce(DateTime last) {