The good news: There is
The bad news: There isn't a built-in class to do this. You'll need to work out your own algorithm
The simplest thing I can think up right now would be:
ORDER BY StartDate (in a query, obviously) so you don't need to worry about ordering things yourself in Apex (based on the StartDate)
- Build a
Map<OpportunityLineItem, List<OpportunityLineItem>> so you can separate and hold individual OLIs for each OppId-PBEId pair
- Using an SObject as a map key is a fantastic way to easily (and quickly) perform multi-field comparisons
- You just need to be careful to never alter the object instance you use as the key after you put it into the map
- Iterate over the keyset of that map, with a nested loop over the list it contains as a value.
- Declare and initialize a counter to 0
- Declare a
Date variable to later track the end date
- In the inner loop
- if the end date is null or not in the same month as the current start date, zero the counter
- figure out the number of months between the current start and end dates, and add it to the counter
- If your counter is >= 12, congrats! you found a consecutive 12-month period. Record that OLI somewhere, or set a field, or something. Then
break; to get out of the inner loop
- Set the end date variable (declared in the outer loop) to the current end date. This is the end of the inner loop
By ordering by the StartDate we only need to worry about whether or not the current StartDate matches with the previous EndDate (as opposed to needing to search the rest of the list for a matching EndDate). If there are any gaps, we can simply start over in trying to find a 12-month run.
Declaring the count and date variables in the outer loop helps to prevent issues where you forget to clear the variable. It ensures that each new List of OLIs that you iterate over has a clean slate to work with.
The downsides there are that this is technically
O(n^2) due to the nested loop (but realistically, it should behave closer to
O(n)), and it doesn't handle overlapping dates.
The main point is that it is possible. I would expect that there is a more efficient approach out there, and you may need to make adjustments to fit the requirements you have.
Breaking down a problem into smaller sub-problems like this is an important skill for programmers. "This would be easier to figure out if X" is usually a good place to start ("X" here being "the OLIs were already in ascending date order").