.net - primer - ultimo dia del mes
¿Cómo determinar el último día hábil en un mes determinado? (9)
Primero, obtenga el último día del mes. Luego continúe decreciendo hasta que haya pasado el comienzo del mes o haya alcanzado una fecha que valide como un "día hábil".
¿Cómo puedo calcular el último día hábil del mes en .NET?
Suponiendo que los días hábiles sean de lunes a viernes (esto no incluye vacaciones), esta función debe devolver la respuesta correcta:
Function GetLastBusinessDay(ByVal Year As Integer, ByVal Month As Integer) As DateTime
Dim LastOfMonth As DateTime
Dim LastBusinessDay As DateTime
LastOfMonth = New DateTime(Year, Month, DateTime.DaysInMonth(Year, Month))
If LastOfMonth.DayOfWeek = DayOfWeek.Sunday Then
LastBusinessDay = LastOfMonth.AddDays(-2)
ElseIf LastOfMonth.DayOfWeek = DayOfWeek.Saturday Then
LastBusinessDay = LastOfMonth.AddDays(-1)
Else
LastBusinessDay = LastOfMonth
End If
Return LastBusinessDay
End Function
propósito general, pseudocódigo:
Day day = getLastDayOfMonth
int days = getDaysInMonth
for i = days to 0
if day is weekday
if day is not holiday
return day
end if
end if
day = prevDay
days--
end for
throw exception because no business day was found in the month
Function GetLastDay(ByVal month As Int32, ByVal year As Int32) As Date
Dim D As New Date(year, month, Date.DaysInMonth(year, month))
For i As Integer = 0 To Date.DaysInMonth(year, month)
Select Case D.AddDays(-i).DayOfWeek
Case DayOfWeek.Saturday, DayOfWeek.Sunday ''Not a weekday
Case Else ''Is a weekday. Flag as first weekday found
Return D.AddDays(-i)
''you can add other code here which could also do a check for holidays or ther stuff since you have a proper date value to look at in the loop
End Select
Next
End Function
Podría pensar en este simple código de C # que le da el último día hábil del mes actual. Esto solo toma el sábado o el domingo como días festivos. Las vacaciones locales específicas del país deben manejarse de forma manual.
private DateTime GetLastBusinessDayOfCurrentMonth()
{
var lastDayOfCurrentMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));
if(lastDayOfCurrentMonth.DayOfWeek == DayOfWeek.Sunday)
lastDayOfCurrentMonth = lastDayOfCurrentMonth.AddDays(-2);
else if(lastDayOfCurrentMonth.DayOfWeek == DayOfWeek.Saturday)
lastDayOfCurrentMonth = lastDayOfCurrentMonth.AddDays(-1);
return lastDayOfCurrentMonth;
}
Lo haría así durante la semana laboral de lunes a viernes:
var holidays = new List<DateTime>{/* list of observed holidays */};
DateTime lastBusinessDay = new DateTime();
var i = DateTime.DaysInMonth(year, month);
while (i > 0)
{
var dtCurrent = new DateTime(year, month, i);
if(dtCurrent.DayOfWeek < DayOfWeek.Saturday && dtCurrent.DayOfWeek > DayOfWeek.Sunday &&
!holidays.Contains(dtCurrent))
{
lastBusinessDay = dtCurrent;
i = 0;
}
else
{
i = i - 1;
}
}
Se me ocurrió un método adicional que se puede utilizar para obtener el día hábil anterior o actual más cercano que luego se puede usar para obtener el último día hábil del mes; esto también se tiene en cuenta si se está ajustando para las vacaciones de fin de semana:
public static DateTime LastBusinessDayInMonth(int year, int month, bool adjustForWeekend = true)
{
var lastDay = DateTime.DaysInMonth(year, month);
return PreviousOrCurrentBusinessDay(new DateTime(year, month, lastDay), adjustForWeekend);
}
public static DateTime PreviousOrCurrentBusinessDay(DateTime? beforeOrOnDate = null, bool adjustForWeekend = true)
{
var fromDate = beforeOrOnDate ?? DateTime.Today;
var year = fromDate.Year;
var month = fromDate.Month;
var day = fromDate.Day;
var holidays = UsHolidays(fromDate.Year, true).ToList(); // defined below
var dtCurrent = new DateTime(year, month, day);
while (!(dtCurrent.DayOfWeek < DayOfWeek.Saturday && dtCurrent.DayOfWeek > DayOfWeek.Sunday && !holidays.Contains(dtCurrent)))
{
dtCurrent = dtCurrent.AddDays(-1);
}
return dtCurrent;
}
También utilizo las vacaciones de EE. UU. En mi cálculo que obtengo del siguiente código que desarrollé al mirar esta publicación: http://geekswithblogs.net/wpeck/archive/2011/12/27/us-holiday-list-in- c.aspx
El código se puede ver aquí para eso:
public static IEnumerable<DateTime> UsHolidays(int year, bool adjustForWeekend)
{
return new List<DateTime>()
{
NewYears(year, adjustForWeekend),
MlkDay(year),
PresidentsDay(year),
GoodFriday(year),
MemorialDay(year),
IndependenceDay(year, adjustForWeekend),
LaborDay(year),
Thanksgiving(year),
Christmas(year, adjustForWeekend),
};
}
public static DateTime NewYears(int year, bool adjustForWeekend)
{
//NEW YEARS
return adjustForWeekend ? AdjustForWeekendHoliday(new DateTime(year, 1, 1).Date) : new DateTime(year, 1, 1).Date;
}
public static DateTime MemorialDay(int year)
{
//MEMORIAL DAY -- last monday in May
var memorialDay = new DateTime(year, 5, 31);
var dayOfWeek = memorialDay.DayOfWeek;
while (dayOfWeek != DayOfWeek.Monday)
{
memorialDay = memorialDay.AddDays(-1);
dayOfWeek = memorialDay.DayOfWeek;
}
return memorialDay.Date;
}
public static DateTime IndependenceDay(int year, bool adjustForWeekend)
{
//INDEPENCENCE DAY
return adjustForWeekend ? AdjustForWeekendHoliday(new DateTime(year, 7, 4).Date) : new DateTime(year, 7, 4).Date;
}
public static DateTime LaborDay(int year)
{
//LABOR DAY -- 1st Monday in September
var laborDay = new DateTime(year, 9, 1);
var dayOfWeek = laborDay.DayOfWeek;
while (dayOfWeek != DayOfWeek.Monday)
{
laborDay = laborDay.AddDays(1);
dayOfWeek = laborDay.DayOfWeek;
}
return laborDay.Date;
}
public static DateTime Thanksgiving(int year)
{
//THANKSGIVING DAY - 4th Thursday in November
var thanksgiving = (from day in Enumerable.Range(1, 30)
where new DateTime(year, 11, day).DayOfWeek == DayOfWeek.Thursday
select day).ElementAt(3);
var thanksgivingDay = new DateTime(year, 11, thanksgiving);
return thanksgivingDay.Date;
}
public static DateTime Christmas(int year, bool adjustForWeekend)
{
return adjustForWeekend ? AdjustForWeekendHoliday(new DateTime(year, 12, 25).Date) : new DateTime(year, 12, 25).Date;
}
public static DateTime MlkDay(int year)
{
//Martin Luther King Day -- third monday in January
var MLKDay = new DateTime(year, 1, 21);
var dayOfWeek = MLKDay.DayOfWeek;
while (dayOfWeek != DayOfWeek.Monday)
{
MLKDay = MLKDay.AddDays(-1);
dayOfWeek = MLKDay.DayOfWeek;
}
return MLKDay.Date;
}
public static DateTime PresidentsDay(int year)
{
//President''s Day -- third monday in February
var presDay = new DateTime(year, 2, 21);
var dayOfWeek = presDay.DayOfWeek;
while (dayOfWeek != DayOfWeek.Monday)
{
presDay = presDay.AddDays(-1);
dayOfWeek = presDay.DayOfWeek;
}
return presDay.Date;
}
public static DateTime EasterSunday(int year)
{
var g = year % 19;
var c = year / 100;
var h = (c - c / 4 - (8 * c + 13) / 25 + 19 * g + 15) % 30;
var i = h - h / 28 * (1 - h / 28 * (29 / (h + 1)) * ((21 - g) / 11));
var day = i - ((year + year / 4 + i + 2 - c + c / 4) % 7) + 28;
var month = 3;
if (day > 31)
{
month++;
day -= 31;
}
return new DateTime(year, month, day);
}
public static DateTime GoodFriday(int year)
{
return EasterSunday(year).AddDays(-2);
}
public static DateTime AdjustForWeekendHoliday(DateTime holiday)
{
if (holiday.DayOfWeek == DayOfWeek.Saturday)
{
return holiday.AddDays(-1);
}
return holiday.DayOfWeek == DayOfWeek.Sunday ? holiday.AddDays(1) : holiday;
}
Usando LINQ:
public static DateTime GetLastBussinessDayCurrentMonth(DateTime[] holidays)
{
DateTime todayDateTime = DateTime.Today;
return
Enumerable.Range(1, DateTime.DaysInMonth(todayDateTime.Year, todayDateTime.Month))
.Select(day => new DateTime(todayDateTime.Year, todayDateTime.Month, day))
.Where(
dt =>
dt.DayOfWeek != DayOfWeek.Sunday && dt.DayOfWeek != DayOfWeek.Saturday
&& (holidays == null || !holidays.Any(h => h.Equals(dt))))
.Max(d => d.Date);
}
Explicando
Crear una lista de enteros con todos los días disponibles en el mes
Enumerable.Range(1, DateTime.DaysInMonth(todayDateTime.Year, todayDateTime.Month))
Filtrando solo días que no caen los fines de semana y no caen en vacaciones
.Where(
dt =>
dt.DayOfWeek != DayOfWeek.Sunday && dt.DayOfWeek != DayOfWeek.Saturday
&& (holidays == null || !holidays.Any(h => h.Equals(dt))))
Crear nueva fecha y hora con las fechas filtradas
.Select(day => new DateTime(todayDateTime.Year, todayDateTime.Month, day))
.Max(d => d.Date);
Aquí es cómo encontrar el último día del mes en C #:
DateTime today = DateTime.Today;
DateTime endOfMonth = new DateTime(today.Year,
today.Month,
DateTime.DaysInMonth(today.Year,
today.Month));