La domanda dice che le festività pubbliche non dovrebbero essere considerate, quindi questa risposta fa proprio questo: calcola l'orario di lavoro tenendo conto dei fine settimana, ignorando eventuali festività pubbliche.
Se è necessario tenere conto delle festività pubbliche, è necessario disporre di una tabella separata che elenchi le date per le festività pubbliche, che possono variare di anno in anno e da stato a stato o da paese a paese. La formula principale può rimanere la stessa, ma è necessario sottrarre dalle ore di risultato per le festività pubbliche che rientrano nell'intervallo di date date.
Creiamo una tabella con alcuni dati di esempio che copre vari casi:
CREATE TABLE T (CreatedDate datetime, UpdatedDate datetime);
INSERT INTO T VALUES
('2012-03-05 09:00:00', '2012-03-05 15:00:00'), -- simple part of the same day
('2012-03-05 10:00:00', '2012-03-06 10:00:00'), -- full day across the midnight
('2012-03-05 11:00:00', '2012-03-06 10:00:00'), -- less than a day across the midnight
('2012-03-05 10:00:00', '2012-03-06 15:00:00'), -- more than a day across the midnight
('2012-03-09 16:00:00', '2012-03-12 10:00:00'), -- over the weekend, less than 7 days
('2012-03-06 16:00:00', '2012-03-15 10:00:00'), -- over the weekend, more than 7 days
('2012-03-09 16:00:00', '2012-03-19 10:00:00'); -- over two weekends
In MS SQL Server Io uso la seguente formula:
SELECT
CreatedDate,
UpdatedDate,
DATEDIFF(minute, CreatedDate, UpdatedDate)/60.0 -
DATEDIFF(day, CreatedDate, UpdatedDate)*16 -
DATEDIFF(week, CreatedDate, UpdatedDate)*16 AS BusinessHours
FROM T
che produce il seguente risultato:
+-------------------------+-------------------------+---------------+
| CreatedDate | UpdatedDate | BusinessHours |
+-------------------------+-------------------------+---------------+
| 2012-03-05 09:00:00 | 2012-03-05 15:00:00 | 6 |
| 2012-03-05 10:00:00 | 2012-03-06 10:00:00 | 8 |
| 2012-03-05 11:00:00 | 2012-03-06 10:00:00 | 7 |
| 2012-03-05 10:00:00 | 2012-03-06 15:00:00 | 13 |
| 2012-03-09 16:00:00 | 2012-03-12 10:00:00 | 2 |
| 2012-03-06 16:00:00 | 2012-03-15 10:00:00 | 50 |
| 2012-03-09 16:00:00 | 2012-03-19 10:00:00 | 42 |
+-------------------------+-------------------------+---------------+
Funziona, perché in SQL Server DATEDIFF
restituisce il conteggio del specificato datapart i confini attraversati tra lo punto di arrivo.
Ogni giorno ha 8 ore di lavoro. Calcolo il numero totale di ore tra due date, quindi sottraggo il numero dei midnights moltiplicato per 16 ore non lavorative al giorno, quindi sottraggo il numero di fine settimana moltiplicato per 16 (8 + 8 ore lavorative per Sat + Sun).
Si presuppone inoltre che la data e l'ora di inizio e di fine indicate siano durante l'orario di ufficio.
In MySQL l'equivalente più vicino è TIMESTAMPDIFF
, ma funziona in modo diverso. Calcola effettivamente la differenza in secondi e divide (scartando la parte frazionaria) per il numero di secondi nell'unità scelta.
Quindi, per ottenere i risultati di cui abbiamo bisogno è possibile calcolare la TIMESTAMPDIFF
tra alcuni datetime ancora e CreatedDate
e UpdatedDate
invece di calcolare la differenza tra CreatedDate
e UpdatedDate
direttamente.
Ho scelto 2000-01-03 00:00:00
, che è un lunedì. È possibile scegliere qualsiasi altro lunedì (o domenica, se la settimana inizia domenica) a mezzanotte per la data di ancoraggio.
La query MySQL diventa (vedi SQL Fiddle):
SELECT
CreatedDate,
UpdatedDate,
TIMESTAMPDIFF(MINUTE, CreatedDate, UpdatedDate)/60.0 -
16*(
TIMESTAMPDIFF(DAY, '2000-01-03',UpdatedDate)-
TIMESTAMPDIFF(DAY, '2000-01-03',CreatedDate)
) -
16*(
TIMESTAMPDIFF(WEEK, '2000-01-03',UpdatedDate)-
TIMESTAMPDIFF(WEEK, '2000-01-03',CreatedDate)
) AS BusinessHours
FROM T
cosa hai provato? cosa non funziona ? – Yahia
mi grattavo la logica e gli antipasti sarebbero buoni – yokoyoko
per qualche punto di partenza vedi la mia risposta qui sotto ... – Yahia