获取当年的法定节假日和周末_通过可配置的周末和节假日添加工作日

获取当年的法定节假日和周末

介绍

我已经找到了一个如何计算两个日期之间的工作日数的示例,但是我还没有找到一种发布方法来添加工作日。 Excel最近添加了此功能,但Microsoft尚未将其提供给Access领域。 因此,我承担了这一挑战。 我创建的函数使用户可以指定不包括哪些天数(对于周末),并且还允许排除假日列表。 必须在表格中输入假期才能使用。 我创建了自己的方法来自动从Internet获取此信息,但这是另一篇文章的主题。

桌子

我能想到的最好的方法是列出可用日期,然后递减指定天数的记录。 这意味着我们需要一个日期列表。 不必将它们全部键入一个表中,我们将让Access处理这个问题。 我们需要的是一个包含单个字段的表:

 tbl_ExpansionDigits 
Digit
现在添加10个记录,值从0到9

我们还需要一个假期表。 我的表有一个日期字段和一个名称字段,以便我可以列出假期名称。

 dbo_Holidays 
hDate
hName
表格查询就是这样

我们实际上只需要一个查询。 这就是给我们约会的神奇之处。 我的名字叫qryPossibleDates。

SELECT Cdate([tbl_expansiondigits_1]![Digit]
   +[tbl_expansiondigits_2]![Digit]*10
   +[tbl_expansiondigits_3]![Digit]*100
   +[tbl_expansiondigits_4]![Digit]*1000 
   +[tbl_expansiondigits_5]![Digit]*10000) AS CalcDate, Weekday(CalcDate) AS WeekDayNumber
FROM tbl_expansiondigits AS tbl_expansiondigits_1, tbl_expansiondigits AS tbl_expansiondigits_2, tbl_expansiondigits AS tbl_expansiondigits_3, tbl_expansiondigits AS tbl_expansiondigits_4, tbl_expansiondigits AS tbl_expansiondigits_5
WHERE ((([tbl_expansiondigits_1]![Digit]
   +[tbl_expansiondigits_2]![Digit]*10
   +[tbl_expansiondigits_3]![Digit]*100
   +[tbl_expansiondigits_4]![Digit]*1000
   +[tbl_expansiondigits_5]![Digit]*10000)>=36000));
这使我们的日期从1998年7月24日到10/13/2173(共64,000天)加上工作日的日期(星期日为1,星期六为7)。

首先,我们需要一个函数来将类似二进制的数字转换为十进制值。 我将其用于二进制标志,以了解从计数中排除哪些天。

Private Function ConvertToDecimal(lngBinary As Long) As Long
Dim strNumber As String
Dim i As Integer
Dim lngAccumulator As Long
Dim n As Integer
Dim s As String
Dim p As Integer 
strNumber = Format(lngBinary, "00000000")
p = 1
For i = 8 To 1 Step -1
    s = Mid(strNumber, p, 1)
    If s = "1" Then
        n = CInt(i) - 1
        lngAccumulator = lngAccumulator + 2 ^ n
    End If
    p = p + 1
Next 
ConvertToDecimal = lngAccumulator 
End Function
现在为主要功能。
Public Function AddDays(dteStart As Date, intInterval As Integer, lngExcludePattern As Long) As Date
Dim lngExcludeDates As Long
Dim strSelect As String
Dim strWhere As String
Dim strSQL As String
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim i As Integer 
If lngExcludePattern <> 0 Then
    lngExcludeDates = ConvertToDecimal(lngExcludePattern)
    strSelect = "SELECT CalcDate As AddedDate FROM qryPossibleDates"
    strWhere = "CalcDate = #" & dteStart & "# Or (CalcDate >= #" & dteStart & "# And CalcDate Not In(SELECT hDate FROM dbo_Holidays WHERE hDate >= #" & dteStart & "#)" 
    If (lngExcludeDates And 64) > 0 Then
        strWhere = strWhere & " And WeekDayNumber <> 1"
    End If 
    If (lngExcludeDates And 32) > 0 Then
        strWhere = strWhere & " And WeekDayNumber <> 2"
    End If 
    If (lngExcludeDates And 16) > 0 Then
        strWhere = strWhere & " And WeekDayNumber <> 3"
    End If 
    If (lngExcludeDates And 8) > 0 Then
        strWhere = strWhere & " And WeekDayNumber <> 4"
    End If 
    If (lngExcludeDates And 4) > 0 Then
        strWhere = strWhere & " And WeekDayNumber <> 5"
    End If 
    If (lngExcludeDates And 2) > 0 Then
        strWhere = strWhere & " And WeekDayNumber <> 6"
    End If 
    If (lngExcludeDates And 1) > 0 Then
        strWhere = strWhere & " And WeekDayNumber <> 7"
    End If 
    strWhere = strWhere & ")"
    strSQL = strSelect & " WHERE " & strWhere
    Debug.Print strSQL 
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenDynaset, dbSeeChanges) 
    rst.Move intInterval 
    AddDays = rst!AddedDate 
    Set db = Nothing
    rst.Close
    Set rst = Nothing 
Else
    AddDays = dteStart + intInterval
End If 
End Function
首先,我测试lngExcludePattern中的值。 如果它是0,那么我只是在计算日历天,它跳到底部。 否则,我将构建一个查询字符串,该字符串是从上面添加条件的查询中提取的。 您会注意到它以CalcDate =#“&dteStart&”#“开头 。这是针对dteStart不是查询中包含的日期的情况,因为它确实与所涉及的日期混淆了(我在排除故障后找到了原因我的计数已关闭)。然后它具有仅显示大于或等于dteStart且不在假期列表中的记录的条件,再次将其过滤为大于或等于dteStart(出于性能)。然后测试使用二进制标志来添加其他条件以排除我们不希望包含的星期几,然后打开记录集并使用.Move方法转到记录集中的正确记录以获取日期。是! 使用

要使用此功能,请传递要添加的起始日期x天数(dteStart),要添加的天数(intInterval),然后是要排除的天数(lngExcludePattern)。 前两个非常简单,但是“排除模式”需要更多说明。 我将其设置为二进制标志。 第一个标志是周日,最后一个标志是周六。 因此,如果我希望周末为星期六和星期日,那么我的排除模式将为1000001。如果我也希望排除星期三,那么我的模式将为1001001。如果我只希望排除星期六,则为0000001,也可以输入为1,因为它以长整数形式传递。 因此,如果我想在1/17/16上增加5天(星期六和星期日除外),则可以这样调用函数:

=AddDays(#1/17/16#, 5, 1000001)
结论

可能还有其他方法可以执行此操作,但这似乎是最通用的方法,并且实际上可以完成我想要的操作。 如果有人有任何批评,我欢迎他们。

翻译自: https://bytes.com/topic/access/insights/965404-adding-business-days-configurable-weekend-days-holidays

获取当年的法定节假日和周末

以下是 Java 计算两个日期之间的工作日(排除法定节假日周末)的示例代码: ```java import java.time.DayOfWeek; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; public class WorkingDaysCalculator { public static long getWorkingDays(LocalDate startDate, LocalDate endDate, List<LocalDate> holidays) { long workingDays = 0; LocalDate date = startDate; while (date.isBefore(endDate)) { if (date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY && !holidays.contains(date)) { workingDays++; } date = date.plus(1, ChronoUnit.DAYS); } return workingDays; } public static void main(String[] args) { LocalDate startDate = LocalDate.of(2021, 1, 1); LocalDate endDate = LocalDate.of(2021, 1, 31); List<LocalDate> holidays = new ArrayList<>(); holidays.add(LocalDate.of(2021, 1, 1)); holidays.add(LocalDate.of(2021, 1, 6)); holidays.add(LocalDate.of(2021, 1, 20)); long workingDays = getWorkingDays(startDate, endDate, holidays); System.out.println("Number of working days between " + startDate + " and " + endDate + ": " + workingDays); } } ``` 与前面的示例相比,这个示例增加了一个 `List<LocalDate> holidays` 参数来表示法定节假日的日期。在 `getWorkingDays` 方法中,我们使用 `while` 循环遍历两个日期之间的每一天,并使用 `getDayOfWeek` 方法来判断一周中的哪一天。如果这一天不是周六或周日,且不是法定节假日,则将其计为工作日。最终,我们将工作日数作为方法的返回值,并在 `main` 方法中打印出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值