Días laborables

 Principal Novedades Utilidades Código Enlaces Access Acerca de mí

     
 
Principal
Arriba

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 DiasLlaborables WeekendDays WeekendDays2 WorkingDays     

DiasLaborables

Para calcular los días laborables que hay entre dos fechas basta con calcular los días que hay entre esas dos fechas y restarles los festivos.

Tenemos dos tipos distintos de festivos y, por tanto, tendremos que hacer dos cálculos distintos:

Por un lado, tenemos las fiestas nacionales, locales, etc. que variarán de un sitio a otro y de un año a otro, por lo que no queda más remedio que guardarlas en una tabla al efecto. Calcular cuántas fiestas de éstas hay en un periodo es tan sencillo como hacer un dCount() sobre la tabla de festivos usando como criterio la fecha de inicio y del final.

Por otro lado tenemos los sábados y domingos, que es un dato fijo y podemos obtener mediante cálculos. Habitualmente, este cálculo se hace recorriendo con un bucle todos los días del periodo y comprobando para cada uno si es sábado o domingo; sin embargo una forma más sencilla y bastante más eficaz, que es la que vamos a usar aquí, parte de la idea de que el número de sábados, o domingos, entre dos fechas es igual que el número de semanas que empiezan por sábado, o domingo, entre esas dos fechas. En la práctica resulta que no es así, pues si la fecha de inicio del periodo es sábado o domingo hay un festivo más, pero no es ningún problema: añadimos esta corrección al procedimiento y funciona perfectamente.

En la función DiasLaborables, incluyo todo esto, pero también añado la función WorkingDays que hace exactamente lo mismo, pero separando el cálculo de sábados y domingos que lo hace mediante una llamada a otra función, WeekendDays, de la cual incluyo dos versiones distintas, WeekendDays2 que utiliza el método de calcular los fines de semana con DateDiff() y WeekendDays que hace el cálculo a base de operaciones básicas sin usar ningún bucle ni ninguna función de fecha.

De los tres métodos, el más eficiente es usar WorkingDays con la función WeekendDays pues resulta más rápido; sin embargo, la diferencia de velocidad no es mucha pues la llamada al dCount() es idéntica en ambos casos y es lo que más retarda la función; además lo que se gana en velocidad, apenas nada, se pierde en claridad del procedimiento, por lo que yo aconsejo usar DiasLaborables().

 

'---------------------------------------------------------------------------------------
' Procedure : DiasLaborables
' DateTime  : 25/09/2005
' Author    : José Bengoechea Ibaceta (Chea)
' Purpose   : Calcular el número de días laborables entre dos fechas. Si se
'           : le pasan los argumentos opcionales NombreTablaFestivos y
'           : NombreCampoFestivo, tiene también en cuenta los días festivos
'           : que estén guardados en un campo con nombre NombreCampoFestivo
'           : en la tabla con nombre NombreTablaFestivos.
'            Estás autorizado a utilizar este código dentro de una aplicación
'            siempre que esta nota de autor permanezca inalterada.
'            En el caso de querer publicarlo en una página Web, por favor,
'            contactar con el autor en
'
'                 UA@bengoechea.net
'---------------------------------------------------------------------------------------
'
Public Function DiasLaborables(FechaDesde As Date, FechaHasta As Date, Optional _
    NombreTablaFestivos As String, Optional NombreCampoFestivo As String) As Long
Dim Laborables As Long
   On Error GoTo DiasLaborables_Error
Laborables = 1 + (FechaHasta - FechaDesde)
If NombreTablaFestivos <> "" And NombreCampoFestivo <> "" Then
    Laborables = Laborables - DCount("*", NombreTablaFestivos, "[" & _
        NombreCampoFestivo & "] Between #" & Format(FechaDesde, "mm/dd/yyyy") & _
        "# AND #" & Format(FechaHasta, "mm/dd/yyyy") & "#")
End If
Laborables = Laborables - DateDiff("ww", FechaDesde, FechaHasta, vbSaturday)
Laborables = Laborables - DateDiff("ww", FechaDesde, FechaHasta, vbSunday)
Laborables = Laborables + (Weekday(FechaDesde, vbSunday) = 1)
Laborables = Laborables + (Weekday(FechaDesde, vbSaturday) = 1)
DiasLaborables = Laborables
   On Error GoTo 0
   Exit Function
DiasLaborables_Error:
    MsgBox "Error " & Err.Number & " (" & Err.Description & _
        ") in procedure DiasLaborables"
End Function
 

 

WeekendDays

Para calcular los días hábiles que hay entre dos fechas, debemos calcular primero cuántos sábados y domingos hay para descontarlos. Habitualmente esto se hace recorriendo con un bucle todas las fechas y comprobando en cada una qué día de la semana es, pero yo quería hacerlo directamente sin bucles ni funciones de fechas, con un rendimiento más eficiente aunque apenas se note. Para lo que sí que sirve este ejemplo es para demostrar que las fechas se pueden manejar con las cuatro operaciones básicas.

 

'---------------------------------------------------------------------------------------
' Procedure : WeekendDays
' DateTime  : 19/09/2005 
' Author    : José Bengoechea Ibaceta(Chea)
' Purpose   : Calcular la suma de sábados y domingos entre dos fechas sin utilizar
'           : ni bucles ni funciones de fecha.
'            Estás autorizado a utilizar este código dentro de una aplicación
'            siempre que esta nota de autor permanezca inalterada.
'            En el caso de querer publicarlo en una página Web, por favor,
'            contactar con el autor en
'
'                 UA@bengoechea.net
'---------------------------------------------------------------------------------------
Public Function WeekendDays(DateStart As Date, DateEnd As Date) As Long
    Dim TotalDias As Long, SemanasCompletas As Long, RestoDias As Long, wdResto _
        As Long, wkd As Long
    TotalDias = 1 + DateEnd - DateStart
    SemanasCompletas = TotalDias \ 7
    RestoDias = TotalDias Mod 7
    'Calculamos el día de la semana del primer día del resto
    'wdResto = Weekday(DateEnd - (RestoDias - 1), vbMonday)
    'Como no quiero usar funciones de fecha, en vez de la línea anterioruso la siguiente
    wdResto = 1 + ((DateEnd - (RestoDias - 1) + 5) Mod 7)
    wkd = SemanasCompletas * 2
    'Si el resto de días + el día de la semana (empezando en lunes) es mayor que 6, nos
    ' cabe un sábado y, si además es mayor que 7, nos cabe un domingo.
    If RestoDias > 0 Then
        If (RestoDias + wdResto > 6) Then wkd = wkd + 1
        If (RestoDias > 1) And (RestoDias + wdResto > 7) And _
            (Weekday(DateStart) <> 1) Then wkd = wkd + 1
    End If
    WeekendDays = wkd
End Function

 

 

 

 

WeekendDays2

Una de las formas más directas de calcular sábados y domingos entre dos fechas es comprobar con DateDif ("ww"...) cuántas semanas hay que empiezan por sábado y cuántas que empiecen por domingo y sumarle uno más si la primera fecha para el cálculo es sábado o domingo.

 


'---------------------------------------------------------------------------------------
' Procedure : WeekendDays2
' DateTime  : 24/09/2005 15:23
' Author    : Chea
' Purpose   : Calcular la suma de sábados y domingos entre dos fechas sin utilizar
'           : bucles
'            Estás autorizado a utilizar este código dentro de una aplicación
'            siempre que esta nota de autor permanezca inalterada.
'            En el caso de querer publicarlo en una página Web, por favor,
'            contactar con el autor en
'
'                 UA@bengoechea.net
'---------------------------------------------------------------------------------------
Public Function WeekendDays2(DateStart As Date, DateEnd As Date) As Long
Dim wkd As Long
    wkd = DateDiff("ww", DateStart, DateEnd, vbSaturday) + DateDiff("ww", _
        DateStart, DateEnd, vbSunday)
    
    If Weekday(DateStart, vbSunday) = 1 Then wkd = wkd + 1
    If Weekday(DateStart, vbSaturday) = 1 Then wkd = wkd + 1
    WeekendDays2 = wkd
End Function
 

 

WorkingDays

Basta calcular los días que hay entre dos fechas y restarle los sábados y domingos, que obtenemos con la función WeekEndDays, y los festivos que tenemos en una tabla y que obtenemos con dCount().

 

Option Compare Database
Option Explicit
''---------------------------------------------------------
' WorkingDays
'
' Código escrito originalmente por José Bengoechea Ibaceta
' (Chea) y Juan M Afán de Ribera.
' Estás autorizado a utilizarlo dentro de una aplicación
' siempre que esta nota de autor permanezca inalterada.
' En el caso de querer publicarlo en una página Web,
' por favor, contactar con los autores en
'
'     accessvba@ya.com
'
' Este código se brinda por cortesía de
' José Bengoechea Ibaceta (Chea)
' Juan M. Afán de Ribera
'
Function WorkingDays( _
                    DateStart As Date, _
                    DateEnd As Date, _
                    Optional TableName As String, _
                    Optional FieldName As String) As Long
Dim SQL As String
Dim Holidays As Long
    If DateStart < DateEnd Then
        On Error Resume Next
        Holidays = DCount("*", TableName, "[" & FieldName & "] Between #" _
        & Format(DateStart, "mm/dd/yyyy") & " AND #" & Format(DateEnd, "mm/dd/yyyy") & "#")
        Err.Clear
        WorkingDays = (DateEnd - DateStart) - (Holidays + WeekendDays(DateStart, DateEnd))
    End If
    
End Function