2016-05-25 3 views
0

Я строю службу Windows, и я хочу, чтобы она обрабатывала множество различных фоновых задач с настраиваемыми интервалами.Как рассчитать интервалы таймера для ежемесячного планирования?

Мне сложно определить, как вычислить продолжительность времени, в течение которого таймер должен ждать, прежде чем начать какую-либо задачу.

Я хранить StartDate против задачи и интервального типа: ежедневно, еженедельно, ежемесячно и т.д. Я прибил ежедневно, но не может работать, как сделать ежемесячно ...

Правила, являются:

  • StartDate Если в будущем, а затем ждать промежуток времени между Now и StartDate.

  • Если StartDate в прошлом, тогда запустите задачу в тот же день месяца/времени, что и StartDate, но в текущем/следующем месяце. Так что если StartDate - 15 марта в 09:00, а сегодня - 25 мая, то в следующий раз задача должна быть запущена 15 июня в 09:00.

У меня есть до сих пор с этим. Вот тест приложение, которое принимает ряд тестов и пытается вычислить количество часов между текущим временем (согласно тесту) и фиксированное время начала выполнения задачи:

using System; 
using System.Collections.Generic; 
using System.Linq; 

public class Program 
{ 
    public static void Main() { 

     // Test cases 
     var times = new Dictionary<DateTime,TimeSpan> { 
      { new DateTime(2016, 3, 1, 9, 0, 0), TimeSpan.FromHours(2016)}, 
      { new DateTime(2016, 3, 5, 3, 0, 0), TimeSpan.FromHours(1926)}, 
      { new DateTime(2016, 3, 5, 9, 0, 0), TimeSpan.FromHours(1920)}, 
      { new DateTime(2016, 3, 5, 15, 0, 0), TimeSpan.FromHours(1914)}, 
      { new DateTime(2016, 3, 24, 3, 0, 0), TimeSpan.FromHours(1470)}, 
      { new DateTime(2016, 3, 24, 9, 0, 0), TimeSpan.FromHours(1464)}, 
      { new DateTime(2016, 3, 24, 15, 0, 0), TimeSpan.FromHours(1458)}, 
      { new DateTime(2016, 4, 19, 9, 0, 0), TimeSpan.FromHours(840)}, 
      { new DateTime(2016, 4, 24, 3, 0, 0), TimeSpan.FromHours(726)}, 
      { new DateTime(2016, 4, 24, 9, 0, 0), TimeSpan.FromHours(720)}, 
      { new DateTime(2016, 4, 24, 15, 0, 0), TimeSpan.FromHours(714)}, 
      { new DateTime(2016, 4, 24, 21, 0, 0), TimeSpan.FromHours(708)}, 
      { new DateTime(2016, 5, 6, 3, 0, 0), TimeSpan.FromHours(438)}, 
      { new DateTime(2016, 5, 24, 3, 0, 0), TimeSpan.FromHours(6)}, 
      { new DateTime(2016, 5, 24, 9, 0, 0), TimeSpan.FromHours(0)}, 
      { new DateTime(2016, 5, 24, 15, 0, 0), TimeSpan.FromHours(738)}, 
      { new DateTime(2016, 5, 26, 3, 0, 0), TimeSpan.FromHours(702)}, 
      { new DateTime(2016, 5, 26, 9, 0, 0), TimeSpan.FromHours(696)}, 
      { new DateTime(2016, 5, 26, 15, 0, 0), TimeSpan.FromHours(690)}, 
      { new DateTime(2016, 6, 24, 3, 0, 0), TimeSpan.FromHours(6)}, 
      { new DateTime(2016, 6, 24, 9, 0, 0), TimeSpan.FromHours(0)}, 
      { new DateTime(2016, 6, 24, 15, 0, 0), TimeSpan.FromHours(714)}, 
      { new DateTime(2016, 7, 6, 3, 0, 0), TimeSpan.FromHours(438)}, 
      { new DateTime(2016, 7, 6, 9, 0, 0), TimeSpan.FromHours(432)}, 
      { new DateTime(2016, 7, 6, 15, 0, 0), TimeSpan.FromHours(426)}, 
      { new DateTime(2016, 7, 24, 3, 0, 0), TimeSpan.FromHours(6)}, 
      { new DateTime(2016, 7, 24, 9, 0, 0), TimeSpan.FromHours(0)}, 
      { new DateTime(2016, 7, 24, 15, 0, 0), TimeSpan.FromHours(738)}, 

     }; 


     var startTime = new DateTime(2016, 05, 24, 09, 00, 00); 
     var last = times.First().Key; 


     foreach (var time in times) { 

      var now = time.Key; 
      var expected = time.Value; 

      var timer = startTime.TimeOfDay - now.TimeOfDay; 

      if (now <= startTime)     
       timer += TimeSpan.FromDays((startTime.Date - now.Date).TotalDays); 
      else 
       timer += TimeSpan.FromDays((now.Date.AddMonths(1) - now.Date).TotalDays);     

      if (last.Date != now.Date) Console.WriteLine(); 
      Console.WriteLine($"{now:yyyy-MM-dd HH:mm} -> {startTime:yyyy-MM-dd HH:mm} = {timer:dd\\.hh} {(timer != expected ? "EXPECTED " + expected.ToString("dd\\.hh") : "CORRECT  ")}"); 

      last = now; 

     }   
    }  
} 

Который производит следующий результат:

2016-03-01 09:00 -> 2016-05-24 09:00 = 84.00 CORRECT  

2016-03-05 03:00 -> 2016-05-24 09:00 = 80.06 CORRECT  
2016-03-05 09:00 -> 2016-05-24 09:00 = 80.00 CORRECT  
2016-03-05 15:00 -> 2016-05-24 09:00 = 79.18 CORRECT  

2016-03-24 03:00 -> 2016-05-24 09:00 = 61.06 CORRECT  
2016-03-24 09:00 -> 2016-05-24 09:00 = 61.00 CORRECT  
2016-03-24 15:00 -> 2016-05-24 09:00 = 60.18 CORRECT  

2016-04-19 09:00 -> 2016-05-24 09:00 = 35.00 CORRECT  

2016-04-24 03:00 -> 2016-05-24 09:00 = 30.06 CORRECT  
2016-04-24 09:00 -> 2016-05-24 09:00 = 30.00 CORRECT  
2016-04-24 15:00 -> 2016-05-24 09:00 = 29.18 CORRECT  
2016-04-24 21:00 -> 2016-05-24 09:00 = 29.12 CORRECT  

2016-05-06 03:00 -> 2016-05-24 09:00 = 18.06 CORRECT  

2016-05-24 03:00 -> 2016-05-24 09:00 = 00.06 CORRECT  
2016-05-24 09:00 -> 2016-05-24 09:00 = 00.00 CORRECT  
2016-05-24 15:00 -> 2016-05-24 09:00 = 30.18 CORRECT  

2016-05-26 03:00 -> 2016-05-24 09:00 = 31.06 EXPECTED 29.06 
2016-05-26 09:00 -> 2016-05-24 09:00 = 31.00 EXPECTED 29.00 
2016-05-26 15:00 -> 2016-05-24 09:00 = 30.18 EXPECTED 28.18 

2016-06-24 03:00 -> 2016-05-24 09:00 = 30.06 EXPECTED 00.06 
2016-06-24 09:00 -> 2016-05-24 09:00 = 30.00 EXPECTED 00.00 
2016-06-24 15:00 -> 2016-05-24 09:00 = 29.18 CORRECT  

2016-07-06 03:00 -> 2016-05-24 09:00 = 31.06 EXPECTED 18.06 
2016-07-06 09:00 -> 2016-05-24 09:00 = 31.00 EXPECTED 18.00 
2016-07-06 15:00 -> 2016-05-24 09:00 = 30.18 EXPECTED 17.18 

2016-07-24 03:00 -> 2016-05-24 09:00 = 31.06 EXPECTED 00.06 
2016-07-24 09:00 -> 2016-05-24 09:00 = 31.00 EXPECTED 00.00 
2016-07-24 15:00 -> 2016-05-24 09:00 = 30.18 CORRECT 

Как вы можете видеть, это немного неверно к концу. Каковы расчеты, необходимые для правильного определения количества часов?

+0

не является 'TimeSpan.FromDays ((а - б) .TotalDays)' эквивалент '(а-б) '? –

+0

@IanMercer: Наверное ... Я пробовал много всего, и просто я играл с вычислениями, не пытаясь окончательно его оптимизировать :) – BG100

ответ

1

Попробуйте этот код:

foreach (var time in times) 
{ 
    var now = time.Key; 
    var expected = time.Value;     
    TimeSpan timer; 
    if (now <= startTime) { 
     // no need to do anything here - just substract 
     timer = startTime - now; 
    } 
    else { 
     // normalize start time to current month 
     var normalized = new DateTime(now.Year, now.Month, startTime.Day, startTime.Hour, startTime.Minute, startTime.Second); 
     if (normalized >= now) { 
       // normalized date is later in the same month - substract 
       timer = normalized - now; 
     } 
     else { 
       // normalized date is before current - move to next month 
       timer = normalized.AddMonths(1) - now; 
     } 
    }     

if (last.Date != now.Date) Console.WriteLine(); 
    Console.WriteLine($"{now:yyyy-MM-dd HH:mm} -> {startTime:yyyy-MM-dd HH:mm} = {timer:dd\\.hh} {(timer != expected ? "EXPECTED " + expected.ToString("dd\\.hh") : "CORRECT  ")}"); 
    last = now; 
} 
+0

Это замечательно, спасибо. Протестировано и работает точно по мере необходимости :) – BG100

 Смежные вопросы

  • Нет связанных вопросов^_^