16

我需要知道如何计算美国假期。我需要一个适用于任何年份的解决方案。我不想简单地将日期存储在需要维护的数据库中。

周末放假需要按照美国政府的政策调整到工作日。如果是星期六,则调整为星期五。如果它是星期天,则需要调整到星期一。我知道美国的许多(大多数?)银行都是这样做的。

如何计算美国假期列表?

Public Function getHolidayList(ByVal vYear As Integer) As List(Of Date)

    Dim HolidayList As New List(Of Date)

    '...fill the list with holidays 
    ' New Year's Day            Jan 1
    ' Martin Luther King, Jr. third Mon in Jan
    ' Washington's Birthday third Mon in Feb
    ' Memorial Day          last Mon in May
    ' Independence Day      July 4
    ' Labor Day             first Mon in Sept
    ' Columbus Day          second Mon in Oct
    ' Veterans Day          Nov 11
    ' Thanksgiving Day      fourth Thur in Nov
    ' Christmas Day         Dec 25

    'adjust for weekends

End Function

www.archives.gov

www.usa.gov

www.opm.gov

4

9 回答 9

18

这是一种方法。这种方法的一个缺点是,由于规则是硬编码的,我需要在国会更改规则的罕见事件中更改代码。对于我的内部软件来说这不是问题,但对于其他人来说可能是这样。

此外,我不计算复活节,因为那不是美国联邦假日。参见Nature (1876) 计算复活节日期的算法

Public Function getHolidayList(ByVal vYear As Integer) As List(Of Date)

    Dim FirstWeek As Integer = 1
    Dim SecondWeek As Integer = 2
    Dim ThirdWeek As Integer = 3
    Dim FourthWeek As Integer = 4
    Dim LastWeek As Integer = 5

    Dim HolidayList As New List(Of Date)

    '   http://www.usa.gov/citizens/holidays.shtml      
    '   http://archive.opm.gov/operating_status_schedules/fedhol/2013.asp

    ' New Year's Day            Jan 1
    HolidayList.Add(DateSerial(vYear, 1, 1))

    ' Martin Luther King, Jr. third Mon in Jan
    HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 1, 1), DayOfWeek.Monday, ThirdWeek))

    ' Washington's Birthday third Mon in Feb
    HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 2, 1), DayOfWeek.Monday, ThirdWeek))

    ' Memorial Day          last Mon in May
    HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 5, 1), DayOfWeek.Monday, LastWeek))

    ' Independence Day      July 4
    HolidayList.Add(DateSerial(vYear, 7, 4))

    ' Labor Day             first Mon in Sept
    HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 9, 1), DayOfWeek.Monday, FirstWeek))

    ' Columbus Day          second Mon in Oct
    HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 10, 1), DayOfWeek.Monday, SecondWeek))

    ' Veterans Day          Nov 11
    HolidayList.Add(DateSerial(vYear, 11, 11))

    ' Thanksgiving Day      fourth Thur in Nov
    HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 11, 1), DayOfWeek.Thursday, FourthWeek))

    ' Christmas Day         Dec 25
    HolidayList.Add(DateSerial(vYear, 12, 25))

    'saturday holidays are moved to Fri; Sun to Mon
    For i As Integer = 0 To HolidayList.Count - 1
        Dim dt As Date = HolidayList(i)
        If dt.DayOfWeek = DayOfWeek.Saturday Then
            HolidayList(i) = dt.AddDays(-1)
        End If
        If dt.DayOfWeek = DayOfWeek.Sunday Then
            HolidayList(i) = dt.AddDays(1)
        End If
    Next

    'return
    Return HolidayList

End Function

Private Function GetNthDayOfNthWeek(ByVal dt As Date, ByVal DayofWeek As Integer, ByVal WhichWeek As Integer) As Date
    'specify which day of which week of a month and this function will get the date
    'this function uses the month and year of the date provided

    'get first day of the given date
    Dim dtFirst As Date = DateSerial(dt.Year, dt.Month, 1)

    'get first DayOfWeek of the month
    Dim dtRet As Date = dtFirst.AddDays(6 - dtFirst.AddDays(-(DayofWeek + 1)).DayOfWeek)

    'get which week
    dtRet = dtRet.AddDays((WhichWeek - 1) * 7)

    'if day is past end of month then adjust backwards a week
    If dtRet >= dtFirst.AddMonths(1) Then
        dtRet = dtRet.AddDays(-7)
    End If

    'return
    Return dtRet

End Function
于 2013-08-20T03:21:14.577 回答
12

转换为 C# 作为控制台程序...我需要快速文本文件中的日期:

class Program
{
    public class Holiday
    {
        public string HolidayName { get; set; }
        public DateTime Date { get; set; }

        public Holiday(string holidayName, DateTime date)
        {
            HolidayName = holidayName;
            Date = date;
        }
    }

    public static List<Holiday> getHolidayList(int vYear)
    {
        int FirstWeek = 1;
        int SecondWeek = 2;
        int ThirdWeek = 3;
        int FourthWeek = 4;
        int LastWeek = 5;

        List<Holiday> HolidayList = new List<Holiday>();

        //   http://www.usa.gov/citizens/holidays.shtml      
        //   http://archive.opm.gov/operating_status_schedules/fedhol/2013.asp

        // New Year's Day            Jan 1
        HolidayList.Add(new Holiday("NewYears", new DateTime(vYear, 1, 1)));

        // Martin Luther King, Jr. third Mon in Jan
        HolidayList.Add(new Holiday("MLK", GetNthDayOfNthWeek(new DateTime(vYear, 1, 1), DayOfWeek.Monday, ThirdWeek)));

        // Washington's Birthday third Mon in Feb
        HolidayList.Add(new Holiday("WashingtonsBDay", GetNthDayOfNthWeek(new DateTime(vYear, 2, 1), DayOfWeek.Monday, ThirdWeek)));

        // Memorial Day          last Mon in May
        HolidayList.Add(new Holiday("MemorialDay", GetNthDayOfNthWeek(new DateTime(vYear, 5, 1), DayOfWeek.Monday, LastWeek)));

        // Independence Day      July 4
        HolidayList.Add(new Holiday("IndependenceDay", new DateTime(vYear, 7, 4)));

        // Labor Day             first Mon in Sept
        HolidayList.Add(new Holiday("LaborDay", GetNthDayOfNthWeek(new DateTime(vYear, 9, 1), DayOfWeek.Monday, FirstWeek)));

        // Columbus Day          second Mon in Oct
        HolidayList.Add(new Holiday("Columbus", GetNthDayOfNthWeek(new DateTime(vYear, 10, 1), DayOfWeek.Monday, SecondWeek)));

        // Veterans Day          Nov 11
        HolidayList.Add(new Holiday("Veterans", new DateTime(vYear, 11, 11)));

        // Thanksgiving Day      fourth Thur in Nov
        HolidayList.Add(new Holiday("Thanksgiving", GetNthDayOfNthWeek(new DateTime(vYear, 11, 1), DayOfWeek.Thursday, FourthWeek)));

        // Christmas Day         Dec 25
        HolidayList.Add(new Holiday("Christmas", new DateTime(vYear, 12, 25)));

        //saturday holidays are moved to Fri; Sun to Mon
        foreach (var holiday in HolidayList)
        {
            if (holiday.Date.DayOfWeek == DayOfWeek.Saturday)
            {
                holiday.Date = holiday.Date.AddDays(-1);
            }
            if (holiday.Date.DayOfWeek == DayOfWeek.Sunday)
            {
                holiday.Date = holiday.Date.AddDays(1);
            }
        }

        //return
        return HolidayList;

    }

    private static System.DateTime GetNthDayOfNthWeek(DateTime dt, DayOfWeek dayofWeek, int WhichWeek)
    {
        //specify which day of which week of a month and this function will get the date
        //this function uses the month and year of the date provided

        //get first day of the given date
        System.DateTime dtFirst = new DateTime(dt.Year, dt.Month, 1);

        //get first DayOfWeek of the month
        System.DateTime dtRet = dtFirst.AddDays(6 - (int)dtFirst.AddDays(-1 * ((int)dayofWeek + 1)).DayOfWeek);

        //get which week
        dtRet = dtRet.AddDays((WhichWeek - 1) * 7);

        //if day is past end of month then adjust backwards a week
        if (dtRet >= dtFirst.AddMonths(1))
        {
            dtRet = dtRet.AddDays(-7);
        }

        //return
        return dtRet;

    }

    static void Main(string[] args)
    {
        for(int ii = 2013; ii < 2100; ii++)
        {
            var holidays = getHolidayList(ii);

            foreach (var holiday in holidays)
            {
                Console.WriteLine(holiday.HolidayName + ": " + holiday.Date.ToShortDateString());
            }
        }
    }
}
于 2013-09-13T15:46:53.563 回答
6

作为参考,联邦假期列表在5 US Code § 6103 中定义。假期

  • 元旦,1 月 1 日。
  • 一月的第三个星期一,马丁路德金的生日。
  • 华盛顿诞辰,二月的第三个星期一。
  • 阵亡将士纪念日,五月的最后一个星期一。
  • Juneteenth国家独立日,6 月 19 日。(2021 年新增)
  • 独立日,7 月 4 日。
  • 劳动节,九月的第一个星期一。
  • 哥伦布日,十月的第二个星期一。
  • 退伍军人节,11 月 11 日。
  • 感恩节,十一月的第四个星期四。
  • 圣诞节,12 月 25 日。

对于周一至周五的普通工人,周六的假期将在前周五举行。我在其他地方读到过,周日的假期将在下周一举行。

于 2019-10-18T18:02:06.970 回答
2

CodeProject 上的 Jay Muntz 使用 XML 文件存储规则,对假期进行了出色的实现。不过,该代码不会针对周末进行调整。

此外,他的纳税日版本(4 月 15 日)也没有纠正华盛顿特区的解放日,尽管这可能与这个问题无关。

动态假期日期计算器,Jay Muntz,2006 年 1 月 5 日

于 2013-08-20T03:33:15.050 回答
2

这是我在 C# 中编写的一些代码。每个假期都表示为 Holiday 的一个实例。要获得联邦政府的遵守日期,只需调用对象的 FederalObservance 方法即可。但是请注意,只有一个假期是实际假期;我刚刚创建了两个假期作为示例。

        public static void Main (string[] args)
    {
        Holiday SatHoliday = new Holiday ("Satman", 2015, 11, 20);
        Holiday Thanksgiving = new Holiday ("Thanksgiving", 2015, 11, 3, DayOfWeek.Thursday);
        Holiday[] holidays = new Holiday[] { SatHoliday, Thanksgiving };

    }
}
class Holiday
{
    public DateTime hDate;
    public String name;
    public Holiday(String name, int year, int month, int day)
    {
        this.name = name;
        this.hDate = new DateTime (year, month, day);
    }
        public Holiday(String name, int year, int month, int weekNum/* Weeks are numbered starting with 0. So, the first week would be 0, the second week 1, etc.*/, DayOfWeek dayOfWeek)
    {
        this.name = name;
        DateTime firstOfMonth = new DateTime (year, month, 1);
        this.hDate = firstOfMonth.AddDays (7 * weekNum + (int)dayOfWeek - (int)firstOfMonth.DayOfWeek);
    }
    public DateTime FederalObservance()
    {

                    if (hDate.DayOfWeek == DayOfWeek.Saturday) {
                        return hDate.AddDays (-1);
                    } else if (hDate.DayOfWeek == DayOfWeek.Sunday) {
                        return hDate.AddDays (1);
        } else {
            return hDate;
        }
    }
}
于 2015-11-20T00:07:40.937 回答
1

非常感谢您的回答 D_Bester。我试图在 VBA for Excel 中执行此操作。

我将您的 VB 代码翻译成 Excel 的 VBA。我想我会在这里发布我的代码,以供其他可能尝试该语言的人使用。

Sub displayHolidays()
    Dim myHolidayList As New Collection
    Set myHolidayList = GetHolidayList(2005)

    For x = 1 To (myHolidayList.Count)
        Debug.Print myHolidayList(x)
    Next
End Sub

Function GetHolidayList(ByVal vYear As Integer) As Collection
    Const FirstWeek As Integer = 1
    Const SecondWeek As Integer = 2
    Const ThirdWeek As Integer = 3
    Const FourthWeek As Integer = 4
    Const LastWeek As Integer = 5
    Const DayofWeek_Monday As Integer = 2
    Const DayofWeek_Thursday As Integer = 5
    Const DayofWeek_Saturday As Integer = 7
    Const DayofWeek_Sunday As Integer = 1

    Dim holidayList As New Collection
    Dim finalHolidayList As New Collection

    '   http://www.usa.gov/citizens/holidays.shtml
    '   http://archive.opm.gov/operating_status_schedules/fedhol/2013.asp

    ' New Year's Day            Jan 1
    holidayList.Add (DateSerial(vYear, 1, 1))

    ' Martin Luther King, Jr. third Mon in Jan
    holidayList.Add (GetNthDayOfNthWeek(DateSerial(vYear, 1, 1), DayofWeek_Monday, ThirdWeek))

    ' Washington's Birthday third Mon in Feb
    holidayList.Add (GetNthDayOfNthWeek(DateSerial(vYear, 2, 1), DayofWeek_Monday, ThirdWeek))

    ' Memorial Day          last Mon in May
    holidayList.Add (GetNthDayOfNthWeek(DateSerial(vYear, 5, 1), DayofWeek_Monday, LastWeek))

    ' Independence Day      July 4
    holidayList.Add (DateSerial(vYear, 7, 4))

    ' Labor Day             first Mon in Sept
    holidayList.Add (GetNthDayOfNthWeek(DateSerial(vYear, 9, 1), DayofWeek_Monday, FirstWeek))

    ' Columbus Day          second Mon in Oct
    holidayList.Add (GetNthDayOfNthWeek(DateSerial(vYear, 10, 1), DayofWeek_Monday, SecondWeek))

    ' Veterans Day          Nov 11
    holidayList.Add (DateSerial(vYear, 11, 11))

    ' Thanksgiving Day      fourth Thur in Nov
    holidayList.Add (GetNthDayOfNthWeek(DateSerial(vYear, 11, 1), DayofWeek_Thursday, FourthWeek))

    ' Christmas Day         Dec 25
    holidayList.Add (DateSerial(vYear, 12, 25))

    'saturday holidays are moved to Fri; Sun to Mon
    For Each dt In holidayList
        If Weekday(dt) = DayofWeek_Saturday Then
            dt = DateAdd("d", -1, dt)
        End If
        If Weekday(dt) = DayofWeek_Sunday Then
            dt = DateAdd("d", 1, dt)
        End If
        finalHolidayList.Add dt
    Next dt

    'return
    Set GetHolidayList = finalHolidayList
End Function

Function GetNthDayOfNthWeek(ByVal dt As Date, ByVal DayofWeek As Integer, ByVal WhichWeek As Integer) As Date
    'specify which day of which week of a month and this function will get the date
    'this function uses the month and year of the date provided
    Dim dtFirst As Date
    Dim innerDate As Date
    Dim monthAdd As Date

    'get first day of the given date
    dtFirst = DateSerial(Year(dt), Month(dt), 1)

    'get first DayOfWeek of the month
    innerDate = DateAdd("d", -DayofWeek, dtFirst)
    GetNthDayOfNthWeek = DateAdd("d", (7 - Weekday(innerDate)), dtFirst)

    'get which week
    GetNthDayOfNthWeek = DateAdd("d", ((WhichWeek - 1) * 7), GetNthDayOfNthWeek)

    'if day is past end of month then adjust backwards a week
    monthAdd = DateAdd("m", 1, dtFirst)
    If GetNthDayOfNthWeek >= monthAdd Then
        GetNthDayOfNthWeek = DateAdd("d", (-7), GetNthDayOfNthWeek)
    End If
End Function
于 2020-05-01T17:57:10.117 回答
0

Nager.Date 支持美国的公共假期,完整的源代码可在github 上获得许多其他国家的支持。

努吉特

PM> install-package Nager.Date

例子:

获取一年中的所有公共假期

var publicHolidays = DateSystem.GetPublicHoliday("US", 2017);

检查日期是否为公共假期

if (DateSystem.IsPublicHoliday(date, "US"))
{
    //logic
}
于 2017-01-14T09:14:16.857 回答
0

周六>>周五和周日>>周一周末规则有一些极端情况:2022 年元旦是周六,但我的雇主不想遵守到 12 月 31 日,因为假期的年份会改变(他们正在创建一个 2022 年浮动假期。)
我曾负责一个支持在每月特定日期(包括最后一天)进行长期资金转移的应用程序。周末规则是推迟到星期一,而假期规则是第二天——当 8 月 31 日是星期六时,这两个规则都适用,一些用户反对推迟到 9 月 3 日星期二。所以一个新规则是向前推进到周五,当月的最后一天登陆一个为期三天的周末。关于复活节 - 纽约证券交易所因耶稣受难日而关闭,因此复活节计算是一个有效的商业案例。
有时,仅每年输入一次假期是更好的用户解决方案。

于 2021-12-15T01:07:12.397 回答
0

这是使用 Lync 的 C# 解决方案。我没有看到使用这种方法的任何其他答案。我将一个月中的所有日子都放入 DateTime 类型的列表中,然后使用 Lync 准确选择我想要的内容。是的,这会占用更多的时间/内存,但如果这不是最关键的优先级,那么看看它的读取有多容易......

/// <summary>
/// Find the Nth day of the month that matches the given dayOfWeek
/// </summary>
/// <param name="year">The year</param>
/// <param name="month">The month number 1 - 12</param>
/// <param name="dayOfWeek">The day of the week</param>
/// <param name="occurance">Take the Nth day found</param>
/// <returns></returns>
public static DateTime GetNthDayOfMonth(int year, int month, DayOfWeek dayOfWeek, int occurance)
{
    return GetDaysInMonth(year, month).Where(d => d.DayOfWeek == dayOfWeek).Skip(occurance - 1).FirstOrDefault();
}

/// <summary>
/// Find the Nth last day of the month that matches the given dayOfWeek
/// </summary>
/// <param name="year">The year</param>
/// <param name="month">The month number 1 - 12</param>
/// <param name="dayOfWeek">The day of the week</param>
/// <param name="occurance">Take the Nth day found</param>
/// <returns></returns>
public static DateTime GetNthLastDayOfMonth(int year, int month, DayOfWeek dayOfWeek, int occurance)
{
    return GetDaysInMonth(year, month).Where(d => d.DayOfWeek == dayOfWeek).Reverse().Skip(occurance - 1).FirstOrDefault();
}

/// <summary>
/// Put all dates of the month into a list that lync can work with
/// </summary>
/// <param name="year">The year</param>
/// <param name="month">The month number 1 - 12</param>
/// <returns></returns>
public static List<DateTime> GetDaysInMonth(int year, int month)
{
    List<DateTime> days = new List<DateTime>();
    var d = new DateTime(year, month, 1);
    while(d.Month == month)
    {
        days.Add(d);
        d = d.AddDays(1);
    }
    return days;
}
于 2018-02-13T15:49:47.610 回答