2010-12-06 7 views
0

j'ai besoin de calculer le nombre de jours de travail entre deux dates. une journée de travail est un jour quelconque du lundi au vendredi, sauf les jours fériés. le code ci-dessous le fait, mais il utilise une boucle. est-ce que quelqu'un voit un moyen de se débarrasser de la boucle ou au moins l'optimiser?s'il vous plaît aider à optimiser cette boucle

grâce Konstantin


using System; 
using System.Linq; 

namespace consapp 
{ 
    static class Program 
    { 
     static void Main(string[] args) 
     { 
      var holidays = new DateTime[] { new DateTime(2010, 11, 23), new DateTime(2010, 11, 30) }; 

      var date_start = new DateTime(2010, 12, 3); 
      var date_end = date_start.AddDays(-9.9); 
      var duration = (date_end - date_start).Duration(); 

      for (var d = date_end; d < date_start; d = d.Date.AddDays(1)) 
      { 
       if (holidays.Contains(d.Date) || d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday) 
       { 
        duration -= TimeSpan.FromDays(1) - d.TimeOfDay; 
       } 
      } 
      Console.WriteLine(duration); 
     } 
    } 
} 

+5

Avez-vous essayé d'abord si cela fonctionne correctement avant d'essayer de l'optimiser? Avez-vous profilé le code pour vous assurer que c'est le goulot d'étranglement? –

+0

Quelles sont les plages de dates généralement utilisées par votre programme? À quel point le code fonctionne-t-il maintenant et à quel point avez-vous besoin de le faire? Bien que je sois certain qu'il existe des façons plus optimales de le faire, je confirmerais d'abord que les résultats sont médiocres. –

+0

duplicata possible de [Calculer le nombre de jours ouvrables entre deux dates?] (Http://stackoverflow.com/questions/1617049/calculate-the-number-of-business-days-between-two-dates) – NotMe

Répondre

0

Je voudrais étudier un algorithme comme celui-ci. (Désolé, aucun code fourni.)

  1. Comptez le nombre de semaines complètes de 7 jours entre votre date de début et la date de fin. Vous devriez être capable de le faire avec les objets .NET DateTime et TimeSpan.
  2. Pour chaque semaine complète de 7 jours, ajoutez 5 jours à votre résultat.
  3. Déterminez les semaines partielles, y compris vos dates de début et de fin.
  4. Parcourez vos vacances et réduisez votre résultat de 1 pour chaque jour férié entre votre date de début et votre date de fin. Le bouclage est meilleur ici parce qu'il y a probablement beaucoup moins de jours fériés à boucler que jours entre votre date de début et de fin.

Amusez-vous!

EDIT: Pour le code source, consultez cette réponse: Calculate the number of business days between two dates?

+0

Merci John, comme vous le voyez, ma question a un code qui n'est pas pire que celui fourni dans la réponse à laquelle vous faites référence. :) – akonsu

+0

@akonsu: Non, cette réponse n'est pas équivalente (que ce soit en concept ou en performance pratique) à votre code. Votre code itère chaque jour entre les deux dates. À mesure que la plage de dates s'élargit, votre code croît linéairement avec cette taille, alors que cette approche est fondamentalement constante. –

+0

je parlais de la réponse dans la question similaire: http://stackoverflow.com/questions/1617049/calculate-the-number-of-business-days-between-two-dates – akonsu

0

performance est-elle vraiment un problème ici? À moins que le profilage ne suggère le contraire, je suppose que ce code ne ralentit pas vraiment votre application. Ses performances devraient être bonnes à moins de calculer les jours de travail pour des milliers d'intervalles longs par seconde.

Si votre liste de jours fériés est beaucoup plus longue que deux dates, convertissez-la en HashSet<T> qui a O (1) temps de recherche.

Et bien sûr, vous pouvez contourner le code. Donc, vous ne bouclez pas les jours dans l'intervalle, mais pendant les vacances. Ensuite, il vous suffit de calculer le nombre de jours de la semaine dans l'intervalle (devrait être simple math) et soustraire le nombre de jours fériés qui tombent un jour de la semaine.

Si cela est vraiment nécessaire, vous pouvez pré-calculer les jours de travail depuis une date fixe, puis soustraire le résultat de la recherche du début de la période du résultat de la recherche à la fin de la période.

0

si vous voulez un code plus rapide, ne boucle pas sur chaque jour de la plage:

supprimer de votre liste des jours fériés tous les jours fériés qui tombent dimanche ou samedi, utilisez alors les méthodes timespan pour vous donner le nombre de jours entre les deux dates. Avec un peu de maths (pensez à la division entière par 7) vous pouvez obtenir le nombre de jours du lundi au jeudi dans cette plage, soustrayez le nombre de jours fériés qui ne tombent pas le week-end de ce nombre et vous avez terminé.

+0

donc il semble que vous dites que je dois seulement boucler sur la liste des vacances (pour trouver ceux qui sont dans ma plage de dates) et se débarrasser de ma boucle sur l'intervalle de temps. – akonsu

+0

@akonsu - c'est vrai; la liste des jours fériés est (probablement) une liste beaucoup plus petite à boucler. Le reste n'est que quelques opérateurs mathématiques. – Assaf

0

Juste rouler avec tel quel. Cela ne va pas perdre beaucoup de temps puisque les limites sont petites. Lorsque vous avez du code de travail, continuez. Pas besoin d'optimiser impitoyablement le code sans raison.

0

juste parce que j'ai commencé cela comme un puzzle amusant, voici le code:

[Test] 
    public void TestDateTime() { 
     var start = DateTime.Now.Date; 
     var end = DateTime.Now.Date.AddDays(35); 
     var workdays = (end - start).Days - ((end - start).Days/7)*2 
      - (((end - start).Days%7==0)?0:(((int)start.DayOfWeek==0)?1:Math.Max(Math.Min((int)start.DayOfWeek + (end - start).Days%7 - 6, 2), 0))); 
     new []{DateTime.Now.AddDays(19), DateTime.Now.AddDays(20)}.ToList().ForEach(
      x => { if (x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday) workdays--; }); 
     Console.Out.WriteLine("workdays = {0}", workdays); 
    } 

jour de Noël et le jour de boxe sont inclus comme jours fériés.

+0

c'est cool, merci. ce code (ainsi que le code que j'ai trouvé dans la question connexe) ne fonctionne pas pour des jours partiels cependant. – akonsu

+0

pouvez-vous expliquer ce que vous voulez pour les jours partiels? Il devrait être facile d'adapter ce que j'ai ici. –

Questions connexes