2016-05-25 6 views
0

Ich baue einen Windows-Dienst, und ich möchte, dass er eine Reihe verschiedener Hintergrundaufgaben in konfigurierbaren Intervallen verarbeitet.Wie berechne ich Timer-Intervalle für die monatliche Planung?

Ich habe eine harte Zeit herauszufinden, wie man die Länge der Zeit berechnet, die der Timer warten muss, bevor er eine Aufgabe startet.

speichere ich ein StartDate gegen die Aufgabe, und ein Intervall Typen: täglich, wöchentlich, monatlich, etc. Ich habe täglich genagelt, aber nicht herausfinden kann, wie monatlich zu tun ...

Die Regeln ist:

  • Wenn die StartDate in der Zukunft liegt, dann die Länge der Zeit zwischen Now und den StartDate warten.

  • Wenn die StartDate in der Vergangenheit ist, dann starten Sie die Aufgabe am selben Tag/Monat wie die StartDate aber im aktuellen/nächsten Monat. Wenn die StartDate also der 15. März um 09:00 Uhr ist und heute der 25. Mai ist, sollte die nächste Aufgabe am 15. Juni um 09:00 Uhr stattfinden.

Ich habe so weit mit diesem. Hier ist eine Test-App, die eine Reihe von Testfällen nimmt und versucht, die Anzahl der Stunden zwischen der aktuellen Zeit zu berechnen (wie pro Testfall) und die feste Startzeit der Aufgabe:

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; 

     }   
    }  
} 

Welche produziert die folgende Ausgabe:

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 

Wie Sie sehen können, geht es gegen Ende ein bisschen falsch. Welche Berechnungen muss ich durchführen, um die Stundenanzahl richtig zu berechnen?

+0

Ist das nicht 'TimeSpan.FromDays ((a - b) .TotalDays)' 'entspricht (a-b)'? –

+0

@IanMercer: Wahrscheinlich ... Ich habe viele viele Dinge ausprobiert und es ist nur ich mit den Berechnungen herumspielen, ohne es schließlich zu optimieren :) – BG100

Antwort

1

diesen Code Versuchen:

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

Das ist perfekt, danke. Getestet und funktioniert genau wie benötigt :) – BG100