public FrequencyComponents GetClientFrequencyComponents() { var result = new FrequencyComponents { Recurrence = Recurrence }; switch (Recurrence) { case RecurrenceType.Instant: break; case RecurrenceType.Daily: result.Time = ClientRunTime.TimeOfDay; break; case RecurrenceType.Weekly: result.Time = ClientRunTime.TimeOfDay; result.WeekDay = ClientRunTime.DayOfWeek; break; case RecurrenceType.Monthly: result.Time = ClientRunTime.TimeOfDay; result.Day = ClientRunTime.Day; result.IsLastDayOfMonth = result.Day >= 28; break; default: throw new ArgumentOutOfRangeException(nameof(Recurrence), Recurrence, $"{nameof(Recurrence)} was out of range."); } return(result); }
public static Frequency FromClientFrequencyComponents(FrequencyComponents clientComponents, TimeZoneInfo clientTimeZone) { if (clientComponents == null) { throw new ArgumentNullException(nameof(clientComponents)); } if (clientTimeZone == null) { throw new ArgumentNullException(nameof(clientTimeZone)); } var clientNow = TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Utc, clientTimeZone); var nearestClientRunTime = clientNow; var minutes = TimeSpan.FromMinutes((clientNow.Hour * 60) + clientNow.Minute); // NOTE: logic should break with InvalidOperationException because of invalid object state if any // ReSharper disable PossibleInvalidOperationException if (clientComponents.Recurrence == RecurrenceType.Daily && clientComponents.Time.Value <= minutes) { nearestClientRunTime = new DateTime(clientNow.Year, clientNow.Month, clientNow.Day).Add(TimeSpan.FromHours(24) + clientComponents.Time.Value); } else if (clientComponents.Recurrence == RecurrenceType.Weekly && (clientNow.DayOfWeek != clientComponents.WeekDay.Value || clientComponents.Time.Value <= minutes)) { var daysToAdd = ((int)clientComponents.WeekDay.Value - (int)clientNow.DayOfWeek + 7) % 7; var nearestWeekDay = clientNow.AddDays(daysToAdd == 0 ? 7 : daysToAdd); nearestClientRunTime = new DateTime(nearestWeekDay.Year, nearestWeekDay.Month, nearestWeekDay.Day).Add(clientComponents.Time.Value); } else if (clientComponents.Recurrence == RecurrenceType.Monthly && (clientNow.Day != clientComponents.Day.Value || clientComponents.Time.Value <= minutes)) { var daysLeftInCurrentMonth = DateTime.DaysInMonth(clientNow.Year, clientNow.Month) - clientNow.Day; var daysToAdd = clientNow.Day < clientComponents.Day.Value ? clientComponents.IsLastDayOfMonth.HasValue && clientComponents.IsLastDayOfMonth.Value ? daysLeftInCurrentMonth : clientComponents.Day.Value - clientNow.Day : clientComponents.IsLastDayOfMonth.HasValue && clientComponents.IsLastDayOfMonth.Value ? daysLeftInCurrentMonth + DateTime.DaysInMonth(clientNow.Year, clientNow.Month + 1) : daysLeftInCurrentMonth + clientComponents.Day.Value; var nearestMonthDay = clientNow.AddDays(daysToAdd); nearestClientRunTime = new DateTime(nearestMonthDay.Year, nearestMonthDay.Month, nearestMonthDay.Day).Add(clientComponents.Time.Value); } else if (clientComponents.Recurrence != RecurrenceType.Instant) { nearestClientRunTime = new DateTime(clientNow.Year, clientNow.Month, clientNow.Day).Add(clientComponents.Time.Value); } // ReSharper restore PossibleInvalidOperationException var result = FromUtcDateTime(TimeZoneInfo.ConvertTime(nearestClientRunTime, clientTimeZone, TimeZoneInfo.Utc), clientComponents.Recurrence, clientTimeZone); return(result); }