[DEMO] CALCOLO GIORNI LAVORATIVI

di il
4 risposte

[DEMO] CALCOLO GIORNI LAVORATIVI

Ho fatto un Demo per il calcolo dei Giorni Lavorativi con Access, che implementa la possibilità di aggiungere delle Festività LOCALI come patrono o altro.

Attualmente considera Festivi tutti i SABATI e DOMENICHE più le Festività Comandate fisse:
1 Gennaio     Capo d'anno
6 Gennaio     Befana
25 Aprile     Liberazione
1 Maggio      Festa Lavoratori
2 Giugno      Repubblica
15 Agosto     Ferragosto
1 Novembre    Ogni Santi
8 Dicembre    Madonna
25 Dicembre   Natale
26 Dicembre   S. Stefano
Non ho inserito la Pasqua in quanto essendo Domenica è già conteggiata come festa, nel caso di flessibilizzazione del codice basterà inserirla.

Il Demo si basa su una Classe che implementa diverse opzioni:


Il sistema è molto Veloce in quanto non scorre i giorni, impiegava troppo, ma calcola i Giorni Totali, quanti Sabati e Domeniche ci sono e le sottrae, poi cicla l'elenco delle Feste Fisse, e verifica se sono nell'intervallo...
Questo permette di rendere molto veloce il tutto.

Chiaramente essendo una Classe, per richiamarla in una Query, basterà creare una Public Function che verrà richiamata come UDF nella sintassi SQL.

Option Compare Database
Option Explicit

Dim dtc     As cWorkingDays

Public Function getWorkingDays(dt1 As Date, dt2 As Date) As Long
    If dtc Is Nothing Then Set dtc = cWorkingDays.Create
    getWorkingDays = dtc.WorkingDays(dt1, dt2)
End Function
Se riesco rendo flessibile la classe per definire i Sabati e le Domeniche come opzionali, come anche le Feste fisse... più avanti.

4 Risposte

  • Re: [DEMO] CALCOLO GIORNI LAVORATIVI

    Posso chiederti perché la scelta di un Singleton, per altro Predeclared, e non una funzione diretta? Suppongo per la comodità della Collection interna e gestibile, ma non ne sono sicuro.

    Vistro che sfrutti l'algoritmo di Gauss, propongo piccola modifica alla funzione che calcola la pasquetta:
    Public Function EasterMonday(ByVal iYear As Integer) As Date
    
        Dim L(6) As Integer, Lj As Integer, Lm As Integer, N As Integer
        
        N = IIf(iYear > 2099, 6, 5)
        
        L(1) = iYear Mod 19: L(2) = iYear Mod 4: L(3) = iYear Mod 7
        L(4) = (19 * L(1) + 24) Mod 30
        L(5) = ((2 * L(2)) + (4 * L(3)) + (6 * L(4)) + N) Mod 7
        L(6) = 22 + L(4) + L(5)
        
        If L(6) > 31 Then
                Lj = L(6) - 31
                Lm = 4
        Else
                Lj = L(6)
                Lm = 3
        End If
        
        EasterMonday = DateAdd("d", 1, (Lj & "/" & Lm & "/" & iYear))
           
    End Function
    
    Così il funzionamento è corretto per tutti gli anni dal 1900 al 2199. Prima con il +5 fisso al posto di N valeva fino al 2099, poi dava risultati non corretti (hai visto mai... XD ).

    Altra domanda: nella BuildNotWorkingDayInYear ci sono due cose che mi incuriosiscono.
    1) Hai volutamente omesso il 25/04 e il 08/12 o son solo sfuggiti?
    2) Perché li carichi castandoli? L'Add diretto
    mNotWorkingDays.Add "25/12", "25/12"
    potrebbe causare problemi?
  • Re: [DEMO] CALCOLO GIORNI LAVORATIVI

    Sgrubak ha scritto:


    Posso chiederti perché la scelta di un Singleton, per altro Predeclared, e non una funzione diretta? Suppongo per la comodità della Collection interna e gestibile, ma non ne sono sicuro.
    La Classe solo perchè ho estrapolato il codice del DEMO da una mia classe più complessa che gestisce tutta una serie di metodi su Date, quindi ho ripulito e riciclato... mi è risultato più comodo
    Si potrebbe tranquillamente gestire tutto in un Modulo standard.
    Chiaramente il vantaggio dell'oggetto è una più corretta gestione delle Property(Let/Get) e del concetto di Private/Public... ma nell'ottica di rendere tutto più snello il modulo standard può essere una buona soluzione.

    La questione del PredeclaredID serve solo per il CONSTRUCTOR della classe, non altro, come vedi invece di dover Dichiarare l'oggetto AS NEW .... in questo modo implementando un constructor(CREATE) nella classe si sfrutta il CREATE ma è solo un dettaglio.

    Sgrubak ha scritto:


    Vistro che sfrutti l'algoritmo di Gauss, propongo piccola modifica alla funzione che calcola la pasquetta:
    ....
    Così il funzionamento è corretto per tutti gli anni dal 1900 al 2199. Prima con il +5 fisso al posto di N valeva fino al 2099, poi dava risultati non corretti (hai visto mai... XD ).
    Grazie ottimo.

    Sgrubak ha scritto:


    Altra domanda: nella BuildNotWorkingDayInYear ci sono due cose che mi incuriosiscono.
    1) Hai volutamente omesso il 25/04 e il 08/12 o son solo sfuggiti?
    Brutalmente dimenticati, come ho sbagliato la Befana, che è il 1° Giugno e non il 6 Gennaio...
    Peraltro ho nominato il 2Giugno come "Liberazione" ma era appunto il 25/4... vabbè dai un po di confusione.

    Li inserisco e correggo, Grazie.

    Sgrubak ha scritto:


    2) Perché li carichi castandoli? L'Add diretto
    mNotWorkingDays.Add "25/12", "25/12"
    potrebbe causare problemi?
    No è un REFUSO, perchè al primo colpo salvavo nella collection la DATA completa di Anno, che ricostruivo, e che poi la castavo in String, poi mi sono accorto che di fatto l'anno non serviva se non per la Pasqua(ed il Lunedì)... era tutto un togli/metti.
    Quindi ho tolto l'anno ma è rimasto il CStr che ovviamente si può togliere e che nella versione flessibile tolgo.

    Ora ho già reso selezionabili le Festività, ovviamente qualche attenzione al fatto che se Escludo i SABATI e/o le DOMENICHE ovviamente devo verificare se le Festività rientrano...
    Esempio se escludo le DOMENICHE devo riprendere la PASQUA, quindi ho pensato di reinserirla e fare un controllo EX-POST condizionato.

    Sembra funzionare abbastanza bene... poi vedo di pubblicarlo.
  • Re: [DEMO] CALCOLO GIORNI LAVORATIVI

    Provo a pubblicare questo, vediamo se è completo:
  • Re: [DEMO] CALCOLO GIORNI LAVORATIVI

    Dovrebbe essere ripulita e completa Versione [R2]:

Devi accedere o registrarti per scrivere nel forum
4 risposte