From 673f8bc2514ca34cdbea610a33a83b166c287943 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Sun, 24 Aug 2025 20:17:14 -0300 Subject: [PATCH 1/8] Added Everyday. --- .../Fluent/1.Run/RunSpecifierTests.cs | 52 ++- .../Fluent/3.Duration/EverydayPeriodTests.cs | 301 ++++++++++++++++++ .../Fluent/3.Duration/PeriodOnceSetTests.cs | 97 ------ .../Scheduler/ScheduleTests.cs | 2 +- FluentScheduler/Common/ThrowHelper.cs | 31 +- FluentScheduler/Fluent/1.Run/RunSpecifier.cs | 29 +- .../Fluent/3.Duration/EverydayPeriod.cs | 130 ++++++++ .../Fluent/3.Duration/PeriodDurationSet.cs | 5 + .../Fluent/3.Duration/PeriodOnceSet.cs | 13 +- 9 files changed, 518 insertions(+), 142 deletions(-) create mode 100644 FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs create mode 100644 FluentScheduler/Fluent/3.Duration/EverydayPeriod.cs diff --git a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs index ed1dac0..8c57393 100644 --- a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs +++ b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs @@ -107,7 +107,6 @@ public void ExecuteOnlyOnceEveryMonday() [Fact] public void ExecuteOnlyOnceEveryTuesday() - { // Arrange var date = new DateTime(2020, 9, 1); @@ -397,7 +396,7 @@ 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; @@ -410,9 +409,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,8 +422,8 @@ 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; @@ -436,18 +437,8 @@ public void EveryWeekend() Equal(expected, calculated); // Arrange - now = new DateTime(2020, 9, 6); - expected = new DateTime(2020, 9, 6); - - // Act - calculated = calculator.Calculate(now); - - // Assert - Equal(expected, calculated); - - // Arrange - now = new DateTime(2020, 9, 7); - expected = new DateTime(2020, 9, 12); + now = new DateTime(2025, 8, 10); + expected = new DateTime(2025, 8, 16); // Act calculated = calculator.Calculate(now); @@ -457,26 +448,29 @@ public void EveryWeekend() } [Fact] - public void EveryDay() + 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 now = new DateTime(2025, 8, 20, 10, 0, 0); + var expected = new DateTime(2025, 8, 20, 10, 0, 0); var fluentCalculator = new FluentTimeCalculator(); var calculator = (ITimeCalculator)fluentCalculator; var run = new RunSpecifier(fluentCalculator); + calculator.Now = () => now; + // Act - run.Every(1).Days().At(15, 0); + run.Everyday(); + var 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 = now.AddHours(1); + expected = expected.AddDays(1); // Act calculated = calculator.Calculate(now); @@ -489,8 +483,8 @@ 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; @@ -518,8 +512,8 @@ 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; @@ -533,8 +527,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/3.Duration/EverydayPeriodTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs new file mode 100644 index 0000000..8503dc2 --- /dev/null +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs @@ -0,0 +1,301 @@ +namespace FluentScheduler.UnitTests; + +using System; +using Xunit; +using static Xunit.Assert; + +public class EverydayPeriodTests +{ + [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 = (ITimeCalculator)fluentCalculator; + var run = new EverydayPeriod(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 = (ITimeCalculator)fluentCalculator; + var run = new EverydayPeriod(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 now = new DateTime(2025, 8, 20, 10, 0, 0); + var expected = new DateTime(2025, 8, 20, 15, 0, 0); + + var timeSpans = new TimeSpan[] { new(15, 0, 0), new(16, 0, 0), new(17, 0, 0) }; + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = (ITimeCalculator)fluentCalculator; + var run = new EverydayPeriod(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.At(timeSpans); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(5.1); + expected = expected.AddHours(1); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated.Value); + + // Arrange + now = now.AddHours(1.1); + expected = expected.AddHours(1); + + // 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 AtMultipleOutOfOrderTimeSpan() + { + // Arrange + var timeSpans = new TimeSpan[] { new(16, 0, 0), new(15, 0, 0), new(17, 0, 0) }; + + var fluentCalculator = new FluentTimeCalculator(); + var run = new EverydayPeriod(fluentCalculator); + + // Act Assert + Throws(() => run.At(timeSpans)); + } + + [Fact] + public void AtMultipleEmptyTimeSpan() + { + var fluentCalculator = new FluentTimeCalculator(); + var run = new EverydayPeriod(fluentCalculator); + + // Act Assert + Throws(() => run.At()); + } + + [Fact] + public void AtMultipleNullTimeSpan() + { + // Arrange + var fluentCalculator = new FluentTimeCalculator(); + var run = new EverydayPeriod(fluentCalculator); + + // Act Assert + Throws(() => run.At(null)); + } + + [Fact] + public void Between17and19() + { + // 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 = (ITimeCalculator)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 Between21and23() + { + // Arrange + var now = new DateTime(2025, 8, 11, 23, 40, 0); + var expectedDate = new DateTime(2025, 08, 12, 21, 30, 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; + + // Act + run.Everyday().Between(from, to); + var calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void Between19and22() + { + // Arrange + var now = new DateTime(2025, 08, 19, 23, 50, 0); + var expectedDate = new DateTime(2025, 08, 20, 19, 30, 0); + + var from = new TimeSpan(19, 30, 0); + var to = new TimeSpan(22, 30, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = (ITimeCalculator)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); + + now = expectedDate.AddMinutes(5); + expectedDate = now; + + calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + now = new DateTime(2025, 08, 20).Add(to).AddMinutes(1); + expectedDate = new DateTime(2025, 08, 21).Add(from); + + 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 from = new TimeSpan(23, 0, 0); + var to = new TimeSpan(2, 0, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = (ITimeCalculator)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); + + // Arrange + now = now.AddHours(1); + expectedDate = now; + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + // Arrange + now = now.AddHours(2); + expectedDate = now; + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + + // Arrange + now = now.AddHours(6); + expectedDate = new DateTime(2025, 08, 25, 23, 0, 0); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expectedDate, calculated.Value); + } +} \ No newline at end of file diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs index dfa5022..f697f64 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs @@ -70,101 +70,4 @@ public void InTheNextMonth() // Assert Equal(expectedDate, calculated.Value); } - - [Fact] - public void Between23and2() - { - - // 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; - - // Act - run.Every(1).Days().Between(from, to); - var calculated = calculator.Calculate(now); - - // Assert - Equal(expectedDate, calculated.Value); - } - - [Fact] - public void Between19and22() - { - // 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 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); - } } 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..2742286 100644 --- a/FluentScheduler/Common/ThrowHelper.cs +++ b/FluentScheduler/Common/ThrowHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Runtime.CompilerServices; namespace FluentScheduler; @@ -35,8 +36,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 +66,26 @@ 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."); + } + + public static void ThrowIfOutOfOrder( + TimeSpan[] values, [CallerArgumentExpression(nameof(values))] string paramName = null) + { + var collection = values.ToList(); + var orderedCollection = collection.OrderBy(t => t).ToList(); + + for (var i = 0; i < collection.Count; i++) + { + if (collection[i] != orderedCollection[i]) + throw new ArgumentException($"\"{paramName}\" is out of order."); + } + } +} \ No newline at end of file diff --git a/FluentScheduler/Fluent/1.Run/RunSpecifier.cs b/FluentScheduler/Fluent/1.Run/RunSpecifier.cs index f8ff851..ca901d7 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 EverydayPeriod 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 EverydayPeriod(_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/EverydayPeriod.cs b/FluentScheduler/Fluent/3.Duration/EverydayPeriod.cs new file mode 100644 index 0000000..bed730c --- /dev/null +++ b/FluentScheduler/Fluent/3.Duration/EverydayPeriod.cs @@ -0,0 +1,130 @@ +using System; + +namespace FluentScheduler; + +/// +/// The "period" run has been set, but not its unit. +/// +public class EverydayPeriod +{ + private readonly FluentTimeCalculator _calculator; + + internal EverydayPeriod(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(_ => + { + ITimeCalculator timeCalculator = _calculator; + var now = timeCalculator.Now(); + + var next = new DateTime(now.Year, now.Month, now.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.ThrowIfOutOfOrder(timeCollection); + ThrowHelper.ThrowIfOutOfMilitaryTimeRange(timeCollection); + + _calculator.PeriodCalculations.Add(_ => + { + ITimeCalculator timeCalculator = _calculator; + var now = timeCalculator.Now(); + + var nextTime = timeCollection[0]; + + foreach (var time in timeCollection) + { + if (now.TimeOfDay < time) + { + nextTime = time; + break; + } + } + + 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( + _ => + { + ITimeCalculator timeCalculator = _calculator; + var now = timeCalculator.Now(); + + var doesNotCrossMidnight = from < to; + + DateTime next; + + if (doesNotCrossMidnight) + { + var startToday = now.Date.Add(from); + var endToday = now.Date.Add(to); + + var nowBetweenStartAndEnd = now >= startToday && now < endToday; + + if (nowBetweenStartAndEnd) + next = now; + else + next = now < startToday ? startToday : startToday.AddDays(1); + } + else + { + var startYesterday = now.Date.AddDays(-1).Add(from); + var endToday = now.Date.Add(to); + + var startToday = now.Date.Add(from); + var endTomorrow = now.Date.AddDays(1).Add(to); + + var nowBetweenStartAndEnd = + (now >= startYesterday && now < endToday) || + (now >= startToday && now < endTomorrow); + + if (nowBetweenStartAndEnd) + next = now; + else + next = now < startToday ? startToday : startToday.AddDays(1); + } + + return next; + } + ); + } +} \ No newline at end of file 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..c1c98ae 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; @@ -67,18 +69,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; } ); } From 6f4a343ea5bd599dd373425079706d34f99f2224 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Sun, 24 Aug 2025 20:35:37 -0300 Subject: [PATCH 2/8] Added EverydayPeriod.Between(int, int) tests. --- .../Fluent/1.Run/RunSpecifierTests.cs | 12 +- .../Fluent/3.Duration/EverydayPeriodTests.cs | 132 +++++++++++++++--- 2 files changed, 116 insertions(+), 28 deletions(-) diff --git a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs index 8c57393..337733e 100644 --- a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs +++ b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs @@ -62,7 +62,7 @@ public void ExecuteOnlyOnceEverySunday() // Act run.Every(DayOfWeek.Sunday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -90,7 +90,7 @@ public void ExecuteOnlyOnceEveryMonday() // Act run.Every(DayOfWeek.Monday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -118,7 +118,7 @@ public void ExecuteOnlyOnceEveryTuesday() // Act run.Every(DayOfWeek.Tuesday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -146,7 +146,7 @@ public void ExecuteOnlyOnceEveryThursday() // Act run.Every(DayOfWeek.Thursday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -174,7 +174,7 @@ public void ExecuteOnlyOnceEveryFriday() // Act run.Every(DayOfWeek.Friday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); @@ -202,7 +202,7 @@ public void EverySaturday() // Act run.Every(DayOfWeek.Saturday); - var calculated = calculator.Calculate(date); + var calculated = calculator.Calculate(date)!; // Assert Equal(expected, calculated); diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs index 8503dc2..0ff4713 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs @@ -21,7 +21,7 @@ public void At() // Act run.At(15, 0); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -31,7 +31,7 @@ public void At() expected = expected.AddDays(1); // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -54,7 +54,7 @@ public void AtTimeSpan() // Act run.At(timeSpan); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -64,7 +64,7 @@ public void AtTimeSpan() expected = expected.AddDays(1); // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -87,7 +87,7 @@ public void AtMultipleTimeSpan() // Act run.At(timeSpans); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -97,7 +97,7 @@ public void AtMultipleTimeSpan() expected = expected.AddHours(1); // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -107,7 +107,7 @@ public void AtMultipleTimeSpan() expected = expected.AddHours(1); // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -117,7 +117,7 @@ public void AtMultipleTimeSpan() expected = new DateTime(2025, 8, 21, 15, 0, 0); // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -145,7 +145,7 @@ public void AtMultipleEmptyTimeSpan() // Act Assert Throws(() => run.At()); } - + [Fact] public void AtMultipleNullTimeSpan() { @@ -158,7 +158,7 @@ public void AtMultipleNullTimeSpan() } [Fact] - public void Between17and19() + public void Between17and19TimeSpan() { // Arrange var now = new DateTime(2025, 08, 24, 16, 30, 0); @@ -175,14 +175,14 @@ public void Between17and19() // Act run.Everyday().Between(from, to); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); } [Fact] - public void Between21and23() + public void Between21and23TimeSpan() { // Arrange var now = new DateTime(2025, 8, 11, 23, 40, 0); @@ -199,14 +199,14 @@ public void Between21and23() // Act run.Everyday().Between(from, to); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); } [Fact] - public void Between19and22() + public void Between19and22TimeSpan() { // Arrange var now = new DateTime(2025, 08, 19, 23, 50, 0); @@ -223,7 +223,7 @@ public void Between19and22() // Act run.Everyday().Between(from, to); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); @@ -231,7 +231,7 @@ public void Between19and22() now = expectedDate.AddMinutes(5); expectedDate = now; - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); @@ -239,14 +239,14 @@ public void Between19and22() now = new DateTime(2025, 08, 20).Add(to).AddMinutes(1); expectedDate = new DateTime(2025, 08, 21).Add(from); - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); } [Fact] - public void Between23and2() + public void Between23and2TimeSpan() { // Arrange var now = new DateTime(2025, 08, 24, 22, 30, 0); @@ -263,7 +263,58 @@ public void Between23and2() // Act run.Everyday().Between(from, to); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; + + // Assert + Equal(expectedDate, calculated.Value); + + // Arrange + now = now.AddHours(1); + expectedDate = now; + + // Act + calculated = calculator.Calculate(now)!; + + // Assert + Equal(expectedDate, calculated.Value); + + // Arrange + now = now.AddHours(2); + expectedDate = now; + + // Act + calculated = calculator.Calculate(now)!; + + // Assert + Equal(expectedDate, calculated.Value); + + // Arrange + now = now.AddHours(6); + expectedDate = new DateTime(2025, 08, 25, 23, 0, 0); + + // Act + 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 fluentCalculator = new FluentTimeCalculator(); + var calculator = (ITimeCalculator)fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.Everyday().Between(23, 0, 2, 0); + var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); @@ -273,7 +324,7 @@ public void Between23and2() expectedDate = now; // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); @@ -283,7 +334,7 @@ public void Between23and2() expectedDate = now; // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); @@ -293,7 +344,44 @@ public void Between23and2() expectedDate = new DateTime(2025, 08, 25, 23, 0, 0); // Act - calculated = calculator.Calculate(now); + calculated = calculator.Calculate(now)!; + + // Assert + Equal(expectedDate, calculated.Value); + } + + [Fact] + public void Between19and22() + { + // Arrange + var now = new DateTime(2025, 08, 19, 23, 50, 0); + var expectedDate = new DateTime(2025, 08, 20, 19, 30, 0); + + var fluentCalculator = new FluentTimeCalculator(); + var calculator = (ITimeCalculator)fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; + + // Act + run.Everyday().Between(19, 30, 22, 30); + var calculated = calculator.Calculate(now)!; + + // Assert + Equal(expectedDate, calculated.Value); + + now = expectedDate.AddMinutes(5); + expectedDate = now; + + calculated = calculator.Calculate(now)!; + + // Assert + Equal(expectedDate, calculated.Value); + + now = new DateTime(2025, 08, 20).Add(new TimeSpan(22, 30, 0)).AddMinutes(1); + expectedDate = new DateTime(2025, 08, 21).Add(new TimeSpan(19, 30, 0)); + + calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); From 6712d5df8e20ea5234b1bde1dfeddf2d3c591d15 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Thu, 28 Aug 2025 21:21:06 -0300 Subject: [PATCH 3/8] Renamed EverydayPeriod to EverydayUnit. --- ...dayPeriodTests.cs => EverydayUnitTests.cs} | 15 ++- FluentScheduler/Fluent/1.Run/RunSpecifier.cs | 4 +- .../Fluent/3.Duration/{Day => }/DayUnit.cs | 123 +++++++++--------- .../{EverydayPeriod.cs => EverydayUnit.cs} | 4 +- .../3.Duration/{Month => }/MonthUnit.cs | 56 ++++---- 5 files changed, 101 insertions(+), 101 deletions(-) rename FluentScheduler.UnitTests/Fluent/3.Duration/{EverydayPeriodTests.cs => EverydayUnitTests.cs} (96%) rename FluentScheduler/Fluent/3.Duration/{Day => }/DayUnit.cs (89%) rename FluentScheduler/Fluent/3.Duration/{EverydayPeriod.cs => EverydayUnit.cs} (97%) rename FluentScheduler/Fluent/3.Duration/{Month => }/MonthUnit.cs (96%) diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs similarity index 96% rename from FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs rename to FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs index 0ff4713..06836ed 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayPeriodTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs @@ -4,7 +4,7 @@ namespace FluentScheduler.UnitTests; using Xunit; using static Xunit.Assert; -public class EverydayPeriodTests +public class EverydayUnitTests { [Fact] public void At() @@ -15,7 +15,7 @@ public void At() var fluentCalculator = new FluentTimeCalculator(); var calculator = (ITimeCalculator)fluentCalculator; - var run = new EverydayPeriod(fluentCalculator); + var run = new EverydayUnit(fluentCalculator); calculator.Now = () => now; @@ -48,7 +48,7 @@ public void AtTimeSpan() var fluentCalculator = new FluentTimeCalculator(); var calculator = (ITimeCalculator)fluentCalculator; - var run = new EverydayPeriod(fluentCalculator); + var run = new EverydayUnit(fluentCalculator); calculator.Now = () => now; @@ -81,7 +81,7 @@ public void AtMultipleTimeSpan() var fluentCalculator = new FluentTimeCalculator(); var calculator = (ITimeCalculator)fluentCalculator; - var run = new EverydayPeriod(fluentCalculator); + var run = new EverydayUnit(fluentCalculator); calculator.Now = () => now; @@ -130,7 +130,7 @@ public void AtMultipleOutOfOrderTimeSpan() var timeSpans = new TimeSpan[] { new(16, 0, 0), new(15, 0, 0), new(17, 0, 0) }; var fluentCalculator = new FluentTimeCalculator(); - var run = new EverydayPeriod(fluentCalculator); + var run = new EverydayUnit(fluentCalculator); // Act Assert Throws(() => run.At(timeSpans)); @@ -140,7 +140,7 @@ public void AtMultipleOutOfOrderTimeSpan() public void AtMultipleEmptyTimeSpan() { var fluentCalculator = new FluentTimeCalculator(); - var run = new EverydayPeriod(fluentCalculator); + var run = new EverydayUnit(fluentCalculator); // Act Assert Throws(() => run.At()); @@ -151,7 +151,7 @@ public void AtMultipleNullTimeSpan() { // Arrange var fluentCalculator = new FluentTimeCalculator(); - var run = new EverydayPeriod(fluentCalculator); + var run = new EverydayUnit(fluentCalculator); // Act Assert Throws(() => run.At(null)); @@ -199,6 +199,7 @@ public void Between21and23TimeSpan() // Act run.Everyday().Between(from, to); + var calculated = calculator.Calculate(now)!; // Assert diff --git a/FluentScheduler/Fluent/1.Run/RunSpecifier.cs b/FluentScheduler/Fluent/1.Run/RunSpecifier.cs index ca901d7..693e311 100644 --- a/FluentScheduler/Fluent/1.Run/RunSpecifier.cs +++ b/FluentScheduler/Fluent/1.Run/RunSpecifier.cs @@ -25,7 +25,7 @@ public PeriodDurationSet Every(int interval) /// /// Runs the job everyday. Tries to run in the same day if the given time was not reached. /// - public EverydayPeriod Everyday() + public EverydayUnit Everyday() { ITimeCalculator timeCalculator = _calculator; @@ -44,7 +44,7 @@ public EverydayPeriod Everyday() return next; }); - return new EverydayPeriod(_calculator); + return new EverydayUnit(_calculator); } /// 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/EverydayPeriod.cs b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs similarity index 97% rename from FluentScheduler/Fluent/3.Duration/EverydayPeriod.cs rename to FluentScheduler/Fluent/3.Duration/EverydayUnit.cs index bed730c..566dee9 100644 --- a/FluentScheduler/Fluent/3.Duration/EverydayPeriod.cs +++ b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs @@ -5,11 +5,11 @@ namespace FluentScheduler; /// /// The "period" run has been set, but not its unit. /// -public class EverydayPeriod +public class EverydayUnit { private readonly FluentTimeCalculator _calculator; - internal EverydayPeriod(FluentTimeCalculator calculator) => _calculator = calculator; + internal EverydayUnit(FluentTimeCalculator calculator) => _calculator = calculator; /// /// Runs the job at the given time of day (military format). 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); + } +} From 47fe6a4b6ad55c7f75fcb99b5ec6add15381b173 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Thu, 28 Aug 2025 21:36:51 -0300 Subject: [PATCH 4/8] Added empty collection validation on At(). --- FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs index c1c98ae..ae02d5a 100644 --- a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs +++ b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs @@ -31,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) From e99408bccc21d4b4961e7a7a6d91cf0b789465b4 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Sun, 14 Sep 2025 18:47:36 -0300 Subject: [PATCH 5/8] Changed Between behaviour in EverydayUnit. --- .../Fluent/1.Run/RunSpecifierTests.cs | 14 +- .../Fluent/3.Duration/EverydayUnitTests.cs | 201 ++++++++++-------- .../Fluent/3.Duration/EverydayUnit.cs | 44 +--- 3 files changed, 128 insertions(+), 131 deletions(-) diff --git a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs index 337733e..fb335fb 100644 --- a/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs +++ b/FluentScheduler.UnitTests/Fluent/1.Run/RunSpecifierTests.cs @@ -462,14 +462,24 @@ public void Everyday() // Act run.Everyday(); - + var calculated = calculator.Calculate(now); // Assert Equal(expected, calculated); // Arrange - now = now.AddHours(1); + now = expected; + expected = expected.AddDays(1); + + // Act + calculated = calculator.Calculate(now); + + // Assert + Equal(expected, calculated); + + // Arrange + now = expected; expected = expected.AddDays(1); // Act diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs index 06836ed..e7402ef 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs @@ -74,27 +74,26 @@ public void AtTimeSpan() public void AtMultipleTimeSpan() { // Arrange - var now = new DateTime(2025, 8, 20, 10, 0, 0); - var expected = new DateTime(2025, 8, 20, 15, 0, 0); - 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 = (ITimeCalculator)fluentCalculator; - var run = new EverydayUnit(fluentCalculator); + var run = new RunSpecifier(fluentCalculator); calculator.Now = () => now; // Act - run.At(timeSpans); + run.Everyday().At(timeSpans); var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); - + // Arrange now = now.AddHours(5.1); - expected = expected.AddHours(1); + expected = expected.Date.Add(timeSpans[1]); // Act calculated = calculator.Calculate(now)!; @@ -104,7 +103,49 @@ public void AtMultipleTimeSpan() // Arrange now = now.AddHours(1.1); - expected = expected.AddHours(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 = (ITimeCalculator)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)!; @@ -158,14 +199,11 @@ public void AtMultipleNullTimeSpan() } [Fact] - public void Between17and19TimeSpan() + public void EverydayAt15() { // 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 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 = (ITimeCalculator)fluentCalculator; @@ -174,22 +212,28 @@ public void Between17and19TimeSpan() calculator.Now = () => now; // Act - run.Everyday().Between(from, to); + 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 Between21and23TimeSpan() + public void EverydayAt16() { // Arrange - var now = new DateTime(2025, 8, 11, 23, 40, 0); - var expectedDate = new DateTime(2025, 08, 12, 21, 30, 0); - - var from = new TimeSpan(21, 30, 0); - var to = new TimeSpan(23, 30, 0); + 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 = (ITimeCalculator)fluentCalculator; @@ -198,23 +242,31 @@ public void Between21and23TimeSpan() calculator.Now = () => now; // Act - run.Everyday().Between(from, to); - + 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 Between19and22TimeSpan() + public void Between17and19TimeSpan() { // Arrange - var now = new DateTime(2025, 08, 19, 23, 50, 0); - var expectedDate = new DateTime(2025, 08, 20, 19, 30, 0); + var now = new DateTime(2025, 08, 24, 16, 30, 0); + var expectedDate = new DateTime(2025, 08, 24, 17, 30, 0); - var from = new TimeSpan(19, 30, 0); - var to = new TimeSpan(22, 30, 0); + var from = new TimeSpan(17, 30, 0); + var to = new TimeSpan(19, 30, 0); var fluentCalculator = new FluentTimeCalculator(); var calculator = (ITimeCalculator)fluentCalculator; @@ -228,19 +280,28 @@ public void Between19and22TimeSpan() // Assert Equal(expectedDate, calculated.Value); + } - now = expectedDate.AddMinutes(5); - expectedDate = now; + [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); - calculated = calculator.Calculate(now)!; + var from = new TimeSpan(21, 30, 0); + var to = new TimeSpan(23, 30, 0); - // Assert - Equal(expectedDate, calculated.Value); + var fluentCalculator = new FluentTimeCalculator(); + var calculator = (ITimeCalculator)fluentCalculator; + var run = new RunSpecifier(fluentCalculator); + + calculator.Now = () => now; - now = new DateTime(2025, 08, 20).Add(to).AddMinutes(1); - expectedDate = new DateTime(2025, 08, 21).Add(from); + // Act + run.Everyday().Between(from, to); - calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); @@ -269,31 +330,8 @@ public void Between23and2TimeSpan() // Assert Equal(expectedDate, calculated.Value); - // Arrange - now = now.AddHours(1); - expectedDate = now; - - // Act - calculated = calculator.Calculate(now)!; - - // Assert - Equal(expectedDate, calculated.Value); - - // Arrange - now = now.AddHours(2); - expectedDate = now; + expectedDate = expectedDate.AddDays(1); - // Act - calculated = calculator.Calculate(now)!; - - // Assert - Equal(expectedDate, calculated.Value); - - // Arrange - now = now.AddHours(6); - expectedDate = new DateTime(2025, 08, 25, 23, 0, 0); - - // Act calculated = calculator.Calculate(now)!; // Assert @@ -320,31 +358,8 @@ public void Between23and2() // Assert Equal(expectedDate, calculated.Value); - // Arrange - now = now.AddHours(1); - expectedDate = now; + expectedDate = expectedDate.AddDays(1); - // Act - calculated = calculator.Calculate(now)!; - - // Assert - Equal(expectedDate, calculated.Value); - - // Arrange - now = now.AddHours(2); - expectedDate = now; - - // Act - calculated = calculator.Calculate(now)!; - - // Assert - Equal(expectedDate, calculated.Value); - - // Arrange - now = now.AddHours(6); - expectedDate = new DateTime(2025, 08, 25, 23, 0, 0); - - // Act calculated = calculator.Calculate(now)!; // Assert @@ -355,8 +370,8 @@ public void Between23and2() public void Between19and22() { // Arrange - var now = new DateTime(2025, 08, 19, 23, 50, 0); - var expectedDate = new DateTime(2025, 08, 20, 19, 30, 0); + var now = new DateTime(2025, 08, 24, 20, 0, 0); + var expectedDate = new DateTime(2025, 08, 24, 20, 0, 0); var fluentCalculator = new FluentTimeCalculator(); var calculator = (ITimeCalculator)fluentCalculator; @@ -365,24 +380,22 @@ public void Between19and22() calculator.Now = () => now; // Act - run.Everyday().Between(19, 30, 22, 30); + run.Everyday().Between(19, 0, 22, 0); var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); - now = expectedDate.AddMinutes(5); - expectedDate = now; + calculated = calculator.Calculate(expectedDate)!; - calculated = calculator.Calculate(now)!; + expectedDate = expectedDate.Date.AddDays(1).Add(new TimeSpan(19, 0, 0)); // Assert Equal(expectedDate, calculated.Value); - now = new DateTime(2025, 08, 20).Add(new TimeSpan(22, 30, 0)).AddMinutes(1); - expectedDate = new DateTime(2025, 08, 21).Add(new TimeSpan(19, 30, 0)); + calculated = calculator.Calculate(expectedDate)!; - calculated = calculator.Calculate(now)!; + expectedDate = expectedDate.AddDays(1); // Assert Equal(expectedDate, calculated.Value); diff --git a/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs index 566dee9..5fb3632 100644 --- a/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs +++ b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs @@ -20,12 +20,12 @@ public void At(int hour, int minute) { ThrowHelper.ThrowIfOutOfMilitaryTimeRange(hour, minute); - _calculator.PeriodCalculations.Add(_ => + _calculator.PeriodCalculations.Add(last => { ITimeCalculator timeCalculator = _calculator; var now = timeCalculator.Now(); - var next = new DateTime(now.Year, now.Month, now.Day, hour, minute, 0); + var next = new DateTime(last.Year, last.Month, last.Day, hour, minute, 0); return now > next ? next.AddDays(1) : next; }); @@ -84,43 +84,17 @@ public void Between(TimeSpan from, TimeSpan to) throw new ArgumentException($"The parameters '{nameof(from)}' and '{nameof(to)}' must not be equal."); _calculator.PeriodCalculations.Add( - _ => + last => { - ITimeCalculator timeCalculator = _calculator; - var now = timeCalculator.Now(); - - var doesNotCrossMidnight = from < to; + 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(); - DateTime next; + var next = new DateTime(last.Year, last.Month, last.Day).Add(from); - if (doesNotCrossMidnight) + if (now >= fromDate && now <= toDate) { - var startToday = now.Date.Add(from); - var endToday = now.Date.Add(to); - - var nowBetweenStartAndEnd = now >= startToday && now < endToday; - - if (nowBetweenStartAndEnd) - next = now; - else - next = now < startToday ? startToday : startToday.AddDays(1); - } - else - { - var startYesterday = now.Date.AddDays(-1).Add(from); - var endToday = now.Date.Add(to); - - var startToday = now.Date.Add(from); - var endTomorrow = now.Date.AddDays(1).Add(to); - - var nowBetweenStartAndEnd = - (now >= startYesterday && now < endToday) || - (now >= startToday && now < endTomorrow); - - if (nowBetweenStartAndEnd) - next = now; - else - next = now < startToday ? startToday : startToday.AddDays(1); + next = now; } return next; From 6af325d4fc8fa29121ef40740b68c27772e0f3a2 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Wed, 17 Sep 2025 20:40:26 -0300 Subject: [PATCH 6/8] Added OutOfOrder and Empty tests in At functions. --- .../Fluent/3.Duration/EverydayUnitTests.cs | 30 ++++++++++++++--- .../Fluent/3.Duration/PeriodOnceSetTests.cs | 32 ++++++++++++++++--- .../Fluent/3.Duration/PeriodOnceSet.cs | 1 + 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs index e7402ef..a4a27e3 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs @@ -90,7 +90,7 @@ public void AtMultipleTimeSpan() // Assert Equal(expected, calculated.Value); - + // Arrange now = now.AddHours(5.1); expected = expected.Date.Add(timeSpans[1]); @@ -121,7 +121,7 @@ public void AtMultipleTimeSpan() // Assert Equal(expected, calculated.Value); } - + [Fact] public void AtMultipleTimeSpan2() { @@ -142,7 +142,7 @@ public void AtMultipleTimeSpan2() // Assert Equal(expected, calculated.Value); - + // Arrange now = now.AddHours(1.1); expected = expected.Date.Add(timeSpans[2]); @@ -227,7 +227,7 @@ public void EverydayAt15() // Assert Equal(expectedDate, calculated.Value); } - + [Fact] public void EverydayAt16() { @@ -400,4 +400,26 @@ public void Between19and22() // Assert Equal(expectedDate, calculated.Value); } + + [Fact] + public void ThrowIfAtOutOfOrder() + { + // Arrange + var fluentCalculator = new FluentTimeCalculator(); + var run = new EverydayUnit(fluentCalculator); + + // Act + Throws(() => run.At(new TimeSpan(10, 0, 0), new TimeSpan(9, 0, 0))); + } + + [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/PeriodOnceSetTests.cs b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs index f697f64..8df41e5 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs @@ -21,7 +21,7 @@ public void At() // Act run.At(8, 40); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); @@ -31,7 +31,7 @@ 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); @@ -44,12 +44,34 @@ public void AtTimeSpan() // Act run.At(timeSpan); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expected, calculated.Value); } + [Fact] + public void ThrowIfAtEmpty() + { + // Arrange + var fluentCalculator = new FluentTimeCalculator(); + var run = new PeriodOnceSet(fluentCalculator); + + // Act + Throws(() => run.At()); + } + + [Fact] + public void ThrowIfAtOutOfOrder() + { + // Arrange + var fluentCalculator = new FluentTimeCalculator(); + var run = new PeriodOnceSet(fluentCalculator); + + // Act + Throws(() => run.At(new TimeSpan(10, 0, 0), new TimeSpan(9, 0, 0))); + } + [Fact] public void InTheNextMonth() { @@ -65,9 +87,9 @@ public void InTheNextMonth() // Act run.Every(1).Months().On(10).At(11, 30); - var calculated = calculator.Calculate(now); + var calculated = calculator.Calculate(now)!; // Assert Equal(expectedDate, calculated.Value); } -} +} \ No newline at end of file diff --git a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs index ae02d5a..57ac342 100644 --- a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs +++ b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs @@ -32,6 +32,7 @@ public void At(int hour, int minute) public void At(params TimeSpan[] timeCollection) { ThrowHelper.ThrowIfEmpty(timeCollection); + ThrowHelper.ThrowIfOutOfOrder(timeCollection); ThrowHelper.ThrowIfOutOfMilitaryTimeRange(timeCollection); foreach (var time in timeCollection) From e19b1482094822e1b1b46198369157c19280ec08 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Wed, 17 Sep 2025 21:24:35 -0300 Subject: [PATCH 7/8] Removed ITimeCalculator cast in unit tests. --- .../Cron/CronTimeCalculatorTests.cs | 33 ++---- .../Fluent/1.Run/RunSpecifierTests.cs | 100 +++++++---------- .../Fluent/2.Once/OnceDurationSetTests.cs | 25 ++--- .../Fluent/2.Once/OnceSetTests.cs | 20 ++-- .../Fluent/3.Duration/Day/DayUnitTests.cs | 10 +- .../Fluent/3.Duration/EverydayUnitTests.cs | 106 +++++++----------- .../Fluent/3.Duration/Month/MonthUnitTests.cs | 5 +- .../3.Duration/PeriodDurationSetTests.cs | 30 ++--- .../Fluent/3.Duration/PeriodOnceSetTests.cs | 26 +---- .../4.Restriction/RestrictionUnitTests.cs | 15 +-- FluentScheduler/Common/ThrowHelper.cs | 14 --- FluentScheduler/Cron/CronTimeCalculator.cs | 12 +- .../Fluent/3.Duration/EverydayUnit.cs | 15 +-- .../Fluent/3.Duration/PeriodOnceSet.cs | 1 - .../Fluent/FluentTimeCalculator.cs | 12 +- 15 files changed, 155 insertions(+), 269 deletions(-) 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 fb335fb..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,9 +54,8 @@ 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); @@ -84,9 +81,8 @@ 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); @@ -112,9 +108,8 @@ public void ExecuteOnlyOnceEveryTuesday() 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); @@ -140,9 +135,8 @@ 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); @@ -168,9 +162,8 @@ 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); @@ -196,9 +189,8 @@ 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); @@ -224,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(); @@ -248,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(); @@ -274,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); @@ -299,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); @@ -324,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); @@ -348,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(); @@ -373,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); @@ -398,9 +383,8 @@ public void EveryWeekday() var now = 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(); @@ -425,9 +409,8 @@ public void EveryWeekend() 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(); @@ -454,9 +437,8 @@ public void Everyday() var now = new DateTime(2025, 8, 20, 10, 0, 0); var expected = new DateTime(2025, 8, 20, 10, 0, 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; @@ -496,9 +478,8 @@ public void EveryMonth() 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); @@ -525,9 +506,8 @@ public void EveryWeek() 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); 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 index a4a27e3..c5520cd 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/EverydayUnitTests.cs @@ -14,14 +14,14 @@ public void At() var expected = new DateTime(2025, 8, 20, 15, 0, 0); var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; + var calculator = fluentCalculator; var run = new EverydayUnit(fluentCalculator); calculator.Now = () => now; // Act run.At(15, 0); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -31,7 +31,7 @@ public void At() expected = expected.AddDays(1); // Act - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -47,14 +47,14 @@ public void AtTimeSpan() var timeSpan = new TimeSpan(15, 0, 0); var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; + var calculator = fluentCalculator; var run = new EverydayUnit(fluentCalculator); calculator.Now = () => now; // Act run.At(timeSpan); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -64,7 +64,7 @@ public void AtTimeSpan() expected = expected.AddDays(1); // Act - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -79,14 +79,14 @@ public void AtMultipleTimeSpan() var expected = new DateTime(2025, 8, 20).Add(timeSpans[0]); var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; + var calculator = fluentCalculator; var run = new RunSpecifier(fluentCalculator); calculator.Now = () => now; // Act run.Everyday().At(timeSpans); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -96,7 +96,7 @@ public void AtMultipleTimeSpan() expected = expected.Date.Add(timeSpans[1]); // Act - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -106,7 +106,7 @@ public void AtMultipleTimeSpan() expected = expected.Date.Add(timeSpans[2]); // Act - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -116,7 +116,7 @@ public void AtMultipleTimeSpan() expected = new DateTime(2025, 8, 21, 15, 0, 0); // Act - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -131,14 +131,14 @@ public void AtMultipleTimeSpan2() var expected = new DateTime(2025, 8, 20).Add(timeSpans[1]); var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; + var calculator = fluentCalculator; var run = new RunSpecifier(fluentCalculator); calculator.Now = () => now; // Act run.Everyday().At(timeSpans); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -148,7 +148,7 @@ public void AtMultipleTimeSpan2() expected = expected.Date.Add(timeSpans[2]); // Act - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); @@ -158,25 +158,12 @@ public void AtMultipleTimeSpan2() expected = new DateTime(2025, 8, 21, 15, 0, 0); // Act - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expected, calculated.Value); } - [Fact] - public void AtMultipleOutOfOrderTimeSpan() - { - // Arrange - var timeSpans = new TimeSpan[] { new(16, 0, 0), new(15, 0, 0), new(17, 0, 0) }; - - var fluentCalculator = new FluentTimeCalculator(); - var run = new EverydayUnit(fluentCalculator); - - // Act Assert - Throws(() => run.At(timeSpans)); - } - [Fact] public void AtMultipleEmptyTimeSpan() { @@ -206,21 +193,21 @@ public void EverydayAt15() var expectedDate = new DateTime(2025, 08, 24, 15, 0, 0); var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; + var calculator = fluentCalculator; var run = new RunSpecifier(fluentCalculator); calculator.Now = () => now; // Act run.Everyday().At(15, 0); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); now = expectedDate; - calculated = calculator.Calculate(expectedDate)!; + calculated = calculator.Calculate(expectedDate); expectedDate = expectedDate.AddDays(1); @@ -236,21 +223,21 @@ public void EverydayAt16() var expectedDate = new DateTime(2025, 08, 24, 16, 0, 0); var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; + var calculator = fluentCalculator; var run = new RunSpecifier(fluentCalculator); calculator.Now = () => now; // Act run.Everyday().At(16, 0); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); now = expectedDate; - calculated = calculator.Calculate(expectedDate)!; + calculated = calculator.Calculate(expectedDate); expectedDate = expectedDate.AddDays(1); @@ -269,14 +256,14 @@ public void Between17and19TimeSpan() var to = new TimeSpan(19, 30, 0); var fluentCalculator = new FluentTimeCalculator(); - var calculator = (ITimeCalculator)fluentCalculator; + var calculator = fluentCalculator; var run = new RunSpecifier(fluentCalculator); calculator.Now = () => now; // Act run.Everyday().Between(from, to); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); @@ -292,16 +279,15 @@ public void Between21and23TimeSpan() 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); + var calculator = new FluentTimeCalculator(); + var run = new RunSpecifier(calculator); calculator.Now = () => now; // Act run.Everyday().Between(from, to); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); @@ -317,22 +303,21 @@ public void Between23and2TimeSpan() var from = new TimeSpan(23, 0, 0); var to = new TimeSpan(2, 0, 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.Everyday().Between(from, to); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); expectedDate = expectedDate.AddDays(1); - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); @@ -345,22 +330,21 @@ public void Between23and2() var now = new DateTime(2025, 08, 24, 22, 30, 0); var expectedDate = new DateTime(2025, 08, 24, 23, 0, 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.Everyday().Between(23, 0, 2, 0); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); expectedDate = expectedDate.AddDays(1); - calculated = calculator.Calculate(now)!; + calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); @@ -373,44 +357,32 @@ public void Between19and22() var now = new DateTime(2025, 08, 24, 20, 0, 0); var expectedDate = new DateTime(2025, 08, 24, 20, 0, 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.Everyday().Between(19, 0, 22, 0); - var calculated = calculator.Calculate(now)!; + var calculated = calculator.Calculate(now); // Assert Equal(expectedDate, calculated.Value); - calculated = calculator.Calculate(expectedDate)!; + calculated = calculator.Calculate(expectedDate); expectedDate = expectedDate.Date.AddDays(1).Add(new TimeSpan(19, 0, 0)); // Assert Equal(expectedDate, calculated.Value); - calculated = calculator.Calculate(expectedDate)!; + calculated = calculator.Calculate(expectedDate); expectedDate = expectedDate.AddDays(1); // Assert Equal(expectedDate, calculated.Value); } - - [Fact] - public void ThrowIfAtOutOfOrder() - { - // Arrange - var fluentCalculator = new FluentTimeCalculator(); - var run = new EverydayUnit(fluentCalculator); - - // Act - Throws(() => run.At(new TimeSpan(10, 0, 0), new TimeSpan(9, 0, 0))); - } [Fact] public void ThrowIfAtEmpty() 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 8df41e5..ac84f5e 100644 --- a/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs +++ b/FluentScheduler.UnitTests/Fluent/3.Duration/PeriodOnceSetTests.cs @@ -13,9 +13,8 @@ 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; @@ -36,9 +35,8 @@ public void AtTimeSpan() 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; @@ -61,17 +59,6 @@ public void ThrowIfAtEmpty() Throws(() => run.At()); } - [Fact] - public void ThrowIfAtOutOfOrder() - { - // Arrange - var fluentCalculator = new FluentTimeCalculator(); - var run = new PeriodOnceSet(fluentCalculator); - - // Act - Throws(() => run.At(new TimeSpan(10, 0, 0), new TimeSpan(9, 0, 0))); - } - [Fact] public void InTheNextMonth() { @@ -79,9 +66,8 @@ public void InTheNextMonth() 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; 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/Common/ThrowHelper.cs b/FluentScheduler/Common/ThrowHelper.cs index 2742286..b3a5dd5 100644 --- a/FluentScheduler/Common/ThrowHelper.cs +++ b/FluentScheduler/Common/ThrowHelper.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Runtime.CompilerServices; namespace FluentScheduler; @@ -75,17 +74,4 @@ internal static void ThrowIfEmpty( if (values.Length == 0) throw new ArgumentException($"\"{paramName}\" can't be empty."); } - - public static void ThrowIfOutOfOrder( - TimeSpan[] values, [CallerArgumentExpression(nameof(values))] string paramName = null) - { - var collection = values.ToList(); - var orderedCollection = collection.OrderBy(t => t).ToList(); - - for (var i = 0; i < collection.Count; i++) - { - if (collection[i] != orderedCollection[i]) - throw new ArgumentException($"\"{paramName}\" is out of order."); - } - } } \ 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/3.Duration/EverydayUnit.cs b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs index 5fb3632..6026799 100644 --- a/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs +++ b/FluentScheduler/Fluent/3.Duration/EverydayUnit.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace FluentScheduler; @@ -38,7 +39,6 @@ public void At(int hour, int minute) public void At(params TimeSpan[] timeCollection) { ThrowHelper.ThrowIfEmpty(timeCollection); - ThrowHelper.ThrowIfOutOfOrder(timeCollection); ThrowHelper.ThrowIfOutOfMilitaryTimeRange(timeCollection); _calculator.PeriodCalculations.Add(_ => @@ -46,16 +46,11 @@ public void At(params TimeSpan[] timeCollection) ITimeCalculator timeCalculator = _calculator; var now = timeCalculator.Now(); - var nextTime = timeCollection[0]; + var orderedTimes = timeCollection.Order(); - foreach (var time in timeCollection) - { - if (now.TimeOfDay < time) - { - nextTime = time; - break; - } - } + var nextTime = orderedTimes.First(); + + nextTime = orderedTimes.FirstOrDefault(t => now.TimeOfDay < t, nextTime); var next = new DateTime(now.Year, now.Month, now.Day).Add(nextTime); diff --git a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs index 57ac342..ae02d5a 100644 --- a/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs +++ b/FluentScheduler/Fluent/3.Duration/PeriodOnceSet.cs @@ -32,7 +32,6 @@ public void At(int hour, int minute) public void At(params TimeSpan[] timeCollection) { ThrowHelper.ThrowIfEmpty(timeCollection); - ThrowHelper.ThrowIfOutOfOrder(timeCollection); ThrowHelper.ThrowIfOutOfMilitaryTimeRange(timeCollection); foreach (var time in timeCollection) 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) { From 8a0811f67be5a61e26af347a8699c6cfc09465d5 Mon Sep 17 00:00:00 2001 From: VitorCioletti Date: Wed, 17 Sep 2025 21:25:25 -0300 Subject: [PATCH 8/8] Changed ThrowHelper to static. --- FluentScheduler/Common/ThrowHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FluentScheduler/Common/ThrowHelper.cs b/FluentScheduler/Common/ThrowHelper.cs index b3a5dd5..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(