/// <summary> /// create instance if this has nonnull RepeatInfo, or null /// </summary> internal static ParsedRepeatInfo Build(string packedValue) { //not rpeating if (string.IsNullOrEmpty(packedValue)) { return(null); } //classify the segments var parsed = new ParsedRepeatInfo(); var segments = packedValue.Split('|', StringSplitOptions.RemoveEmptyEntries); string maxEndTime = DateUtil.ToYMDHM(DateTime.Today.AddYears(1)); parsed.EndTime = maxEndTime; parsed.AutoExtend = false; foreach (string segment in segments) { if (segment.Length < 1) { continue; } char meaning = segment[0]; if (meaning == 'e') { if (segment.Length == 14) { parsed.EndTime = segment[2..];
/// <summary> /// With delayed execution, find all cases where a task should be repeated /// </summary> /// <param name="box">Only inspects box.BoxTime and Repeats</param> /// <param name="includeCurrent">if true, includes the time the box is currently scheduled for</param> /// <param name="allowAbortOnLowClutter">if true, will skip projections after the currently scheduled time, if low clutter</param> public IEnumerable <AgendaEntry> Project(CachedBox box, bool includeCurrent, bool allowAbortOnLowClutter) { //include the specific time it is now scheduled for whether repeating or not if (includeCurrent) { (DateTime? remindAt1, DateTime? remindAt2) = CalcPendingReminder(box); yield return(new AgendaEntry { Box = box, Time = box.BoxTime, PendingPrepReminder = remindAt1, PendingReminder = remindAt2 }); } bool doProjections = box.Repeats != null; if (allowAbortOnLowClutter && box.Visibility == Constants.VISIBILITY_LOWCLUTTER) { doProjections = false; } if (doProjections) { DateTime?max = DateUtil.ToDateTime(box.Repeats.EndTime); if (max == null) { max = DateTime.Today; } //convert add and delete exceptions to datetime strings and start with all the added ones var deleteExceptions = box.Repeats.Entries.Where(e => e.Kind == ParsedRepeatInfo.RepeatKind.DeleteSpecific) .Select(d => d.Date + d.Time); var addExceptions = box.Repeats.Entries.Where(e => e.Kind == ParsedRepeatInfo.RepeatKind.AddSpecific) .Select(d => d.Date + d.Time); var allTimes = new HashSet <string>(); foreach (string t in addExceptions) { allTimes.Add(t); } //go through all patterns and add times for those unless deleted foreach (var pat in box.Repeats.Entries) { //handle add and delete if (pat.Kind == ParsedRepeatInfo.RepeatKind.DeleteSpecific) { continue; } if (pat.Kind == ParsedRepeatInfo.RepeatKind.AddSpecific) { allTimes.Add(pat.Date + pat.Time); continue; } //handle all other pattern kinds (int hr, int mi) = DateUtil.ToHourMinute(pat.Time, 9, 0); DateTime?running = DateUtil.ToDateTime(box.BoxTime); if (running == null) { continue; } for (int iter = 0; iter < 500; ++iter) //infinite loop control { running = NextTime(running.Value, max.Value, pat, hr, mi); if (running == null) { break; } string t2 = DateUtil.ToYMDHM(running.Value); if (deleteExceptions.Contains(t2)) { continue; } allTimes.Add(t2); } } //provide return values foreach (string t in allTimes) { yield return(new AgendaEntry { Box = box, Time = t }); } } }