IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

[JoursOuvrés] Calculer le nombre de jours ouvrés entre 2 dates


Sujet :

C#

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Points : 552
    Points
    552
    Par défaut [JoursOuvrés] Calculer le nombre de jours ouvrés entre 2 dates
    Bonjour,


    Je souhaiterais calculer le nombre total de jours ouvrés entre 2 dates.

    Bon la méthode simple (que je vais faire je crois)
    C'est d'ignorer le samedi et le dimanche.

    La méthode propre en une ligne:
    Une fonction culturelle prévu par .Net qui gère les jours fériés & Co...

    Merci,
    Bien à vous

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Points : 552
    Points
    552
    Par défaut
    Bon ca vous semble cohérent ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    private int DaysIgnoreWeekends(DateTime dtst, DateTime dtend)
    {
           TimeSpan days = dtend.Subtract(dtst);
           int count = 0;
           for (int a = 0; a < days.Days + 1; a++)
           {
               if (dtst.DayOfWeek != DayOfWeek.Saturday && dtst.DayOfWeek != DayOfWeek.Sunday)
                   count++;
               dtst = dtst.AddDays(1.0);
           }
           return count;
    }
    Si y a mieux, plus court, plus propre,
    je suis preneur !

  3. #3
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 252
    Points
    28 252
    Par défaut
    ton problème est avec deux dates très éloignées, la boucle peut être forte consommatrice.

    fait un test avec celle-ci:
    1- pour voir si t'as les mêmes résultats
    2- pour laquelle est plus rapide

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    int Weekdays(DateTime dtmStart, DateTime dtmEnd)
        {
            // This function includes the start and end date in the count if they fall on a weekday
            int dowStart = ((int)dtmStart.DayOfWeek == 0 ? 7 : (int)dtmStart.DayOfWeek);
            int dowEnd = ((int)dtmEnd.DayOfWeek == 0 ? 7 : (int)dtmEnd.DayOfWeek);
            TimeSpan tSpan = dtmEnd - dtmStart;
            if (dowStart <= dowEnd)
            {
                return (((tSpan.Days / 7) * 5) + Math.Max((Math.Min((dowEnd + 1), 6) - dowStart), 0));
            }
            else
            {
                return (((tSpan.Days / 7) * 5) + Math.Min((dowEnd + 6) - Math.Min(dowStart, 6), 5));
            }
        }

    ensuite, il ne faut pas oublier les jours fériés
    moi c'est Louis-Guillaume, ni Louis, ni Guillaume mais Louis-Guillaume et je n'aide pas ceux qui écorchent mon nom

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Points : 552
    Points
    552
    Par défaut
    hum,
    J'ai plus confiance en mon code...

    Visiblement y a des pti soucis avec ta fonction (19/03/2010, 02/04/2010) à l'air d'annoncer une différence de 6 jours :/

    Je prefere privilegier la lisibilié du code, que les performances

    Mais bien essayé merci,
    Héhé

    Les jours fériés c'est un enfer, si c'est pas pris en compte par la framework, je laisse béton

  5. #5
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 252
    Points
    28 252
    Par défaut
    c'est pas mon code, je l'ai trouvé sur un forum. après je le trouve pas moins lisible, c'est juste une formule mathématique, mais elle est p-e erronée effectivement, la tienne est plus facilement testable.

    quant aux jours fériés, ca se gère assez facilement en stockant à part une liste de jour, et en vérifiant simplement si c'est entre les deux dates && si c'est un weekday, et dans ce cas, tu retires 1.
    moi c'est Louis-Guillaume, ni Louis, ni Guillaume mais Louis-Guillaume et je n'aide pas ceux qui écorchent mon nom

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 1 002
    Points : 552
    Points
    552
    Par défaut
    Louis-Guillaume Morand
    C'est cool d'avoir proposé ton code, comme ca si quelqu un tombe ici, il aura le choix !

    En effet, c'est faisable de gérer les jours feriés, mais je vais pas le faire dans mon cas Osef...

    A+

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 2
    Points : 2
    Points
    2
    Par défaut Nombre de jours ouvrables
    Bonjour,

    Je n'ai pas trouvé de solution lisible sur le net donc j'ai écrit ce petit code :
    L'idée est d'isoler les semaines complètes,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     public static int NbWorkingDays(DateTime startDate, DateTime endDate)
            {
                int nbDays = 0;
                while (endDate > startDate && endDate.DayOfWeek != DayOfWeek.Sunday && endDate.DayOfWeek != DayOfWeek.Saturday)
                {
                    endDate = endDate.AddDays(-1);
                    nbDays++;
                }
     
                while (startDate < endDate && startDate.DayOfWeek != DayOfWeek.Saturday && startDate.DayOfWeek != DayOfWeek.Sunday)
                {
                    startDate = startDate.AddDays(1);
                    nbDays++;
                }
     
     
                TimeSpan totalNbDaysSpan = endDate - startDate;
     
     
                nbDays += 5*(totalNbDaysSpan.Days / 7);
                return nbDays;
     
            }
    En espérant vous être utile,

    Marouane
    http://djerbatourisme.com/djerba/

  8. #8
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 252
    Points
    28 252
    Par défaut
    j'ai mis une bonne grosse minute à comprendre le code parce que je voyais pas comment ca pouvait retourner le total.
    l'idée est bien et effectivement c'est sûrement très véloce comme méthode
    moi c'est Louis-Guillaume, ni Louis, ni Guillaume mais Louis-Guillaume et je n'aide pas ceux qui écorchent mon nom

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 2
    Points : 2
    Points
    2
    Par défaut Petite correction
    Bonjour,

    J'avais oublié ce cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (endDate <= startDate) { return 0; }
    A ajouter au début

    Marouane
    http://djerbatourisme.com/djerba/

  10. #10
    Candidat au Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2023
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2023
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Désolé, ce n'est pas du C mais du VBA, mais je suis tombé sur votre vieux thread en effectuant mes recherches.

    Finalement, j'ai refait les calculs par moi-même et j'ai obtenu le code ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    Function j_ouvrés(date1, date2)
    'gestion du fait d inverser les dates'
    debut = date1
    fin = date2
    If debut > fin Then
    fin = date1
    debut = date2
    End If
     
    'on veut compter un jour commencé comme un jour entier'
    fin = fin + 1
     
    dowStart = Weekday(debut, 2) - 1 'lundi = 0 , dimanche =6'
    dif_date = fin - debut
     
    'récupération du nombre de jours hors semaines complètes'
    reste = modulo(dif_date, 7)
    nb_sem = (dif_date - reste) / 7
     
    'gestion des jours restant (hors semaines complètes) et calcul du nombre de jours à prendre en charge'
    restant = modulo((WorksheetFunction.Min(modulo((reste + dowStart), 8), 5) - dowStart), 6)
     
    'cas du dimanche qui est comme un samedi décalé'
      If dowStart > 5 Then 
     
      restant = modulo((WorksheetFunction.Min(modulo((reste + 5), 8), 5) - 5), 6)
          If reste > 1 Then 
              restant = restant + 1
     
          End If
      End If
     
    j_ouvrés = WorksheetFunction.RoundUp(nb_sem * 5 + restant, 0)
     
    End Function
     
    'j ai dû réécrire la fonction modulo qui retournait des nombres négatifs :('
    Function modulo(a, b)
    modulo = (a + b) Mod b
    End Function
    Si ça peut servir à quelqu'un qui passe par là !

  11. #11
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 717
    Points : 5 358
    Points
    5 358
    Par défaut
    Ce code utilise le standard et peut potentiellement être un peu long.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    using System;
    using System.Collections.Generic;
     
    DateTime start = new DateTime(2021, 1, 1);
    DateTime end = new DateTime(2021, 12, 31);
    int businessDays = 0;
     
    // Liste des jours fériés
    List<DateTime> holidays = new List<DateTime>
    {
        new DateTime(2021, 1, 1), // Nouvel An
        new DateTime(2021, 12, 25), // Noël
        // Ajoutez d'autres jours fériés ici...
    };
     
    for (var date = start; date <= end; date = date.AddDays(1))
    {
        if (date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday && !holidays.Contains(date))
        {
            businessDays++;
        }
    }
     
    Console.WriteLine($"Il y a {businessDays} jours ouvrables entre {start} et {end}.");
    Ce code utilise la librairie NodaTime qui est optimisée pour parcourir des plages de dates et est donc plus performant même si la logique est la même :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    using NodaTime;
    using NodaTime.Extensions;
    using System.Collections.Generic;
     
    LocalDate start = new LocalDate(2021, 1, 1);
    LocalDate end = new LocalDate(2021, 12, 31);
    int businessDays = 0;
     
    // Liste des jours fériés
    List<LocalDate> holidays = new List<LocalDate>
    {
        new LocalDate(2021, 1, 1), // Nouvel An
        new LocalDate(2021, 12, 25), // Noël
        // Ajoutez d'autres jours fériés ici...
    };
     
    for (var date = start; date <= end; date = date.PlusDays(1))
    {
        if (date.DayOfWeek != IsoDayOfWeek.Saturday && date.DayOfWeek != IsoDayOfWeek.Sunday && !holidays.Contains(date))
        {
            businessDays++;
        }
    }
     
    Console.WriteLine($"Il y a {businessDays} jours ouvrables entre {start} et {end}.");

  12. #12
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 226
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 226
    Points : 1 791
    Points
    1 791
    Par défaut
    Citation Envoyé par Fardouk Voir le message
    Bonjour,

    Désolé, ce n'est pas du C mais du VBA, mais je suis tombé sur votre vieux thread en effectuant mes recherches.
    en VBA/Excel, il y a plus simple, il y a une fonction qui fait déjà le boulot => https://learn.microsoft.com/fr-fr/of...on.networkdays

  13. #13
    Candidat au Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2023
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Service public

    Informations forums :
    Inscription : Décembre 2023
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par umfred Voir le message
    en VBA/Excel, il y a plus simple, il y a une fonction qui fait déjà le boulot => https://learn.microsoft.com/fr-fr/of...on.networkdays
    Bonjour,

    Effectivement, mais j'avais besoin de tester ces formules pour les transposer dans Power Querry sous power BI et j'avais besoin d'un traitement dans Power Querry intermédiaire avant de passer au DAX...
    Avantage de VBA avec excel : tester sur des dates aléatoires et comparer les résultats avec les formules existantes de Excel.

    Sinon, oui, je connais bien la formule, pas d'inquiétude

    Et comme ma formule ne nécessite pas de récursion ou de parcourt potentiellement gourmand et que c'est avec des fonctions plutôt simples, je voulais partager

    Pour information, je l'ai testé entre le 1/1/1900 et le 12/12/9999 et j'ai le même résultat que Microsoft et question performances : moins de 2 secondes de calcul pour un tableau de 169 calculs de jours ouvrés + le calcul d'Excel qu'il fait sur les mêmes date).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Vxi3] Calcul nombre de jours ouvrés entre 2 dates
    Par Wonsul dans le forum Webi
    Réponses: 2
    Dernier message: 22/04/2013, 16h15
  2. [Dates] Calcul du nombre de jours ouvrés entre 2 dates
    Par Pokerstar dans le forum Langage
    Réponses: 6
    Dernier message: 16/07/2011, 16h02
  3. [Dates] calculer le nombre de jour ouvrable entre 2 dates
    Par pimpmyride dans le forum Langage
    Réponses: 1
    Dernier message: 20/11/2006, 17h10
  4. Réponses: 1
    Dernier message: 10/08/2006, 14h43
  5. Nombre de jours ouvrés entre 2 dates
    Par motlerang dans le forum Langage SQL
    Réponses: 1
    Dernier message: 13/12/2005, 13h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo