La solution MATLAB n'est pas aussi moche que tout le monde le pense (bien qu'elle pourrait probablement être simplifiée en utilisant la Boîte à outils financiers). Pour aller droit au but, voici la solution sous forme d'une fonction qui accepte deux valeurs datetime
:
function workMins = work_time(startTime, endTime)
dateBlock = repmat((dateshift(startTime, 'start', 'day'):...
dateshift(endTime, 'start', 'day')).', 1, 2); %'
dateBlock(:, 1) = dateBlock(:, 1)+hours(8);
dateBlock(:, 2) = dateBlock(:, 2)+hours(17);
dateBlock(1, 1) = max(dateBlock(1, 1), startTime);
dateBlock(end, 2) = min(dateBlock(end, 2), endTime);
dateBlock((datestr(dateBlock(:, 1), 'd') == 'S'), :) = [];
workMins = minutes(sum(max(diff(dateBlock, 1, 2), 0)));
end
Et voici comment tout cela fonctionne...
Tout d'abord, nous avons nos heures de début et de fin en tant que valeurs de type datetime
:
startTime = datetime('22/06/2017 18:00');
endTime = datetime('26/06/2017 09:00');
Maintenant, nous pouvons créer une matrice N-by-2
de datetimes. Chaque ligne correspondra à un jour couvert par la plage de startTime
à endTime
, avec les heures définies à 0:00:00
pour le moment:
dateBlock = repmat((dateshift(startTime, 'start', 'day'):...
dateshift(endTime, 'start', 'day')).', 1, 2);
Ensuite, nous définissons les horaires de la première colonne à 8:00:00
et les horaires de la deuxième colonne à 17:00:00
:
dateBlock(:, 1) = dateBlock(:, 1)+hours(8);
dateBlock(:, 2) = dateBlock(:, 2)+hours(17);
Et maintenant, nous ajoutons startTime
et endTime
8:00:00 à 17:00:00
:
dateBlock(1, 1) = max(dateBlock(1, 1), startTime);
dateBlock(end, 2) = min(dateBlock(end, 2), endTime);
Ensuite, nous supprimons les lignes avec une valeur de jour datestr
de 'S'
(c'est-à-dire un jour de week-end):
dateBlock((datestr(dateBlock(:, 1), 'd') == 'S'), :) = [];
Et enfin, nous prenons les différences de colonnes, les ajoutons (en ignorant les valeurs négatives) et convertissons en minutes:
workMins = minutes(sum(max(diff(dateBlock, 1, 2), 0)));
Et nous obtenons le résultat souhaité:
workMins =
600
ÉDIT:
En ce qui concerne la nouvelle demande, vous pouvez modifier légèrement la fonction pour permettre de passer les heures de début et de fin d'une journée de travail comme ceci:
function workMins = work_time(startTime, endTime, workDayStart, workDayEnd)
dateBlock = repmat((dateshift(startTime, 'start', 'day'):...
dateshift(endTime, 'start', 'day')).', 1, 2); %'
dateBlock(:, 1) = dateBlock(:, 1)+hours(workDayStart);
dateBlock(:, 2) = dateBlock(:, 2)+hours(workDayEnd);
...
Et maintenant vous pouvez l'appeler avec vos plages horaires de travail séparées et ajouter les résultats:
startTime = datetime('22/06/2017 18:00');
endTime = datetime('26/06/2017 09:00');
workTotal = work_time(startTime, endTime, 9.5, 11.5) ...
+ work_time(startTime, endTime, 13, 15);
Ou soustraire une sous-plage d'une plage plus grande:
workTotal = work_time(startTime, endTime, 9.5, 15) ...
- work_time(startTime, endTime, 11.5, 13);
Si vous préférez spécifier les heures de travail comme des chaînes de caractères, vous pouvez écrire la fonction de cette manière:
function workMins = work_time(startTime, endTime, workDayStart, workDayEnd)
dateBlock = repmat((dateshift(startTime, 'start', 'day'):...
dateshift(endTime, 'start', 'day')).', 1, 2); %'
workDayStart = datevec(workDayStart);
workDayEnd = datevec(workDayEnd);
dateBlock(:, 1) = dateBlock(:, 1)+duration(workDayStart(4:6));
dateBlock(:, 2) = dateBlock(:, 2)+duration(workDayEnd(4:6));
...
Et l'utiliser de cette façon:
workTotal = work_time(startTime, endTime, '9:30', '11:30') ...
+ work_time(startTime, endTime, '13:00', '15:00');