I've been trying to figure out this algorithm for a couple days now. I may be lost in a loop in my thinking at this point - it seems like I'm overcomplicating the problem. I'm open to changing the approach, configuration records (or schema) or any other part of the algorithm.
Essentially, I want to perform an action (starting on a variable date) every x months (with optional offset) based on a set of configuration records. The configuration records look like this:
Start Offset | Repeat |
---|---|
3 | 0 |
9 | 0 |
9 | 6 |
An explanation of these records:
- Start 3, Repeat 0
- Complete the action once three months from the start date
- Start 9, Repeat 0
- Complete the action once nine months from the start date
- Start 9, Repeat 6
- Complete the action every 6 months, skipping the first nine months
I've tried the following, but I don't get the output I expect. The results are close, but slightly off and I can't see why.
//start with an arbitrary date
var startDate = DateTime.Parse("2021-01-01");
//determine how many months we want to calculate for; in this case 5 years worth of time
var totalMonths =
(
DateTime.UtcNow.AddYears(5)
.Subtract(startDate)
.Days / 30
) 1;
//get our configuration records
var configList = new List<ConfigItem>(){
new ConfigItem(){StartOffset = 3, Repeat = 0},
new ConfigItem(){StartOffset = 9, Repeat = 0},
new ConfigItem(){StartOffset = 9, Repeat = 6},
}
for (var monthCount = 1; monthCount < totalMonths; monthCount )
{
//select the configs that apply to where we are in the count of months
var configs = configList
// this is a mess, just throwing stuff at the wall here
.Where(tp =>
(tp.StartOffset == monthCount && tp.RepeatMonths == 0)
|| (
tp.RepeatMonths tp.StartOffset <= monthCount
&& tp.RepeatMonths > 0
&& (
tp.RepeatMonths > 0
&& (
(monthCount) % (tp.RepeatMonths)) == tp.StartOffset
|| (monthCount) % (tp.RepeatMonths)==0
)
)
);
foreach (var config in configs)
{
//do something
}
}
Results: Everything seems right except the June (6) records - those shouldn't be there based on the configuration.
Date to do something |
---|
2022-09-15 2:18:14 |
2023-03-15 2:18:14 |
2024-03-15 2:18:14 |
2024-06-15 2:18:14 |
2025-03-15 2:18:14 |
2025-06-15 2:18:14 |
2026-03-15 2:18:14 |
2026-06-15 2:18:14 |
2027-03-15 2:18:14 |
2027-06-15 2:18:14 |
Thanks in advance!
CodePudding user response:
I think your solution would be less complicated if you used the configurations as a starting point instead of the months.
//start with an arbitrary date
var startDate = DateTime.Parse("2021-01-01");
//how far you want to calculate into the future
var endDate = DateTime.UtcNow.AddYears(5);
//get our configuration records
var configList = new List<ConfigItem>(){
new ConfigItem(){StartOffset = 3, Repeat = 0},
new ConfigItem(){StartOffset = 9, Repeat = 0},
new ConfigItem(){StartOffset = 9, Repeat = 6},
};
var listOfDatesToDoSomething = new List<DateTime>();
foreach (var configItem in configList)
{
if (configItem.Repeat == 0)
{
if (startDate.AddMonths(configItem.StartOffset) <= endDate)
{
listOfDatesToDoSomething.Add(startDate.AddMonths(configItem.StartOffset));
}
}
var date = startDate.AddMonths(configItem.Repeat);
while (date < endDate)
{
listOfDatesToDoSomething.Add(date);
date.AddMonths(configItem.Repeat);
}
}