2 votes

c# Obtenir les heures de travail dans un intervalle de temps

Compte tenu de plusieurs périodes de temps, comment puis-je obtenir un tableau qui m'indique le nombre d'heures de travail pour une période donnée ?

Les heures de travail commencent à 9 heures et se terminent à 17 heures.

Exemples :

  1. 15-Nov-2017 16:00 - 17-Nov-2017 12:00 -> Cela devrait me donner un tableau de [1,8,3].

  2. 15-Nov-2017 09:00 - 17-Nov-2017 12:00 -> Cela devrait me donner un tableau de [8,8,1] (Cela semble facile car je peux faire Hrs / 8 et Hrs % 8 pour obtenir le résultat).

  3. 16-Nov-2017 15:00 - 17-Nov-2017 15:00 -> Cela devrait me donner un tableau de [2,6].

C'est la méthode qui me donne actuellement le total des heures de travail entre l'heure de début et l'heure de fin :

protected double getWorkingHrs(DateTime _dtTaskStart, DateTime _dtTaskEnd)
{
    double count = 0;

    for (var i = _dtTaskStart; i < _dtTaskEnd; i = i.AddHours(1))
    {
        if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday)
        {
            if (i.TimeOfDay.Hours >= 9 && i.TimeOfDay.Hours < 17)
            {
                count++;
            }
        }
    }

    return count;
}

Toute aide serait appréciée.

La tâche a montré comme ça dans des blocs de 8 heures. Ainsi, lorsque j'ajoute une tâche de 20 heures, je dois les décomposer en ensembles et les afficher dans la grille. Je dois les diviser car il y a de fortes chances que la tâche d'un jour différent soit assignée à un utilisateur différent et qu'elle ait des notes différentes, etc.

UI for placing tasks

Cheers

2voto

Artak Points 1485

Voici une solution à votre problème :

    public static double[] GetWorkHours(DateTime start, DateTime end, TimeSpan workStartTime, TimeSpan workEndTime)
    {
        IList<double> result = new List<double>();

        if (start > end)
        {
            throw new ArgumentException("Start date is later than end date");
        }

        DateTime currentDate = start.Date;
        while (currentDate <= end.Date)
        {
            if (currentDate.DayOfWeek != DayOfWeek.Saturday && currentDate.DayOfWeek != DayOfWeek.Sunday)
            {
                TimeSpan realStartTime = GetStartTimeForDay(start, end, workStartTime, currentDate);
                TimeSpan realEndTime = GetEndTimeForDay(start, end, workEndTime, currentDate);

                if (realStartTime >= workEndTime || realEndTime <= workStartTime)
                {
                    result.Add(0);
                }
                else
                {
                    result.Add(GetHoursInTimePeriod(realStartTime, realEndTime));
                }
            }

            currentDate = currentDate.AddDays(1);
        }

        return result.ToArray();
    }

    private static TimeSpan GetStartTimeForDay(DateTime start, DateTime end, TimeSpan workStartTime, DateTime day)
    {
        return day == start.Date ? (start.TimeOfDay < workStartTime ? workStartTime : start.TimeOfDay) : workStartTime;
    }

    private static TimeSpan GetEndTimeForDay(DateTime start, DateTime end, TimeSpan workEndTime, DateTime day)
    {
        return day == end.Date ? (end.TimeOfDay < workEndTime ? end.TimeOfDay : workEndTime) : workEndTime;
    }

    private static double GetHoursInTimePeriod(TimeSpan start, TimeSpan end)
    {
        return (end - start).TotalHours;
    }

1voto

Timothy Groote Points 3800

Bien que ce ne soit pas le plus joli (faire une boucle à cliquet sur les dates en ajoutant des heures est un peu inélégant), votre fonction peut être adaptée pour fournir un énumérable avec le nombre d'heures de travail (ou d'heures ouvrables comme on les appelle plus communément) pour chaque jour comme suit :

protected IEnumerable<double> getWorkingHrsPerDay(DateTime _dtTaskStart, DateTime _dtTaskEnd)
{
    double count = 0;
    DateTime lastHandledDate = _dtTaskStart.Date;
    for (var i = _dtTaskStart; i < _dtTaskEnd; i = i.AddHours(1))
    {
        if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday)
        {
            if (i.TimeOfDay.Hours >= 9 && i.TimeOfDay.Hours < 17)
            {
                count++;
            }
        }
        //if we have started to count the hours for a new day
        if (lastHandledDate.Date != i.Date)
        {
            lastHandledDate = i.Date;
            double hourCount = count;
            //reset our hour count
            count = 0;
            //we return the count of the last day
            yield return hourCount;
        }
        lastHandledDate = i.Date;
    }
}

vous pourriez alors faire ce qui suit avec la méthode ToArray de LINQ :

double[] hoursPerDay = getWorkingHrsPerDay(beginDate, endDate).ToArray();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X