Как рассчитать отпуск для США
Мне нужно знать, как рассчитать отпуск в США. Мне нужно решение, которое работает на любой год. Я не хотел просто хранить даты в базе данных, которую нужно было бы поддерживать.
Для праздников в выходные дни необходимо следовать политике правительства США, чтобы приспособиться к буднему дню. Если он выпадает на субботу, он устанавливается на пятницу. Если он выпадает на воскресенье, его необходимо настроить на понедельник. Я понимаю, что многие (большинство?) Банков в США делают это одинаково.
Как рассчитать список праздников в США?
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 Day Jan 1
' Martin Luther King, Jr. third Mon in Jan
' Washington 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
Ответы
Ответ 1
Это один из способов сделать это. Слабостью этого метода является то, что, поскольку правила жестко закодированы, мне нужно будет изменить код в редком случае, когда конгресс изменил правила. Для моего внутреннего программного обеспечения это не проблема, но это может быть для других.
Также я не рассчитываю Пасху, так как это не федеральный праздник США. См. Природа (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 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 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
Ответ 2
Преобразован в С# в качестве консольной программы... Мне нужны даты в текстовом файле быстро:
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 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 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());
}
}
}
}
Ответ 3
Jay Muntz на CodeProject имеет отличную реализацию праздников, используя XML файл для хранения правил. Однако этот код не настроен на выходные.
Также его версия налогового дня (15 апреля) не исправляется в День эмансипации в Вашингтоне, хотя это может быть иррелеванно для этого вопроса.
Динамический калькулятор даты отпуска Jay Muntz, 5 января 2006 г.
Ответ 4
Вот код, который я набрал в С#. Каждый праздник представлен в качестве примера Праздника. Чтобы получить дату соблюдения федеральным правительством, просто назовите объект методом 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;
}
}
}
Ответ 5
Nager.Date поддерживает публичный отпуск для США, полный исходный код доступен на github, поддерживается много других coutries.
NuGet
PM> install-package Nager.Date
Пример:
Получить все праздничные дни года
var publicHolidays = DateSystem.GetPublicHoliday("US", 2017);
Проверьте, не является ли дата праздничным днем
if (DateSystem.IsPublicHoliday(date, "US"))
{
//logic
}
Ответ 6
Вот решение С#, использующее Lync. Я не видел никаких других ответов, используя этот подход. Я помещаю все дни месяца в список типа 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;
}
Ответ 7
Для справки, список федеральных праздников определен в 5 кодекса США § 6103. Праздники:
- Новый год, 1 января.
- День рождения Мартина Лютера Кинга-младшего
третий понедельник января.
- День рождения Вашингтона, третий понедельник
Февраль.
- День поминовения, последний понедельник мая.
- День независимости, 4 июля.
- День труда, первый понедельник сентября.
- День Колумба, второй понедельник октября.
- День ветеранов, 11 ноября.
- День благодарения, четвертый четверг ноября.
- Рождество 25 декабря.
Для обычных работников с понедельника по пятницу выходные в субботу будут отмечаться в пятницу раньше. В других местах я читал, что праздничные дни посадки в воскресенье будут отмечаться в следующий понедельник.