c# - sistema - ¿Cómo determino si una fecha determinada es el N ° día entre semana del mes?
sacar el mes de una fecha en c# (8)
Esto es lo que estoy tratando de hacer: dada una fecha, un día de la semana y un número entero n
, determine si la fecha es el día n
del mes.
Por ejemplo:
entrada de
1/1/2009,Monday,2
sería falso porque1/1/2009
no es el segundo lunesentrada del
11/13/2008,Thursday,2
volvería verdadero porque es el segundo jueves
¿Cómo puedo mejorar esta implementación?
private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n)
{
int d = date.Day;
return date.DayOfWeek == dow && (d/ 7 == n || (d/ 7 == (n - 1) && d % 7 > 0));
}
En esta respuesta , se debe voltear el siguiente código:
// Complete the gap to the nth week
dt = dt.AddDays((nth - 1) * 7);
if(dt.Month != month)
{
// we skip to the next month, we throw an exception
throw new ArgumentOutOfRangeException(”The given month has less than ” nth.ToString() ” ”
day_of_the_week.ToString() “s”);
}
En caso de que desee una lista de fechas para un lapso de tiempo (no solo una) para el N ° Día de la semana de un mes, puede usar esto:
internal static List<DateTime> GetDatesForNthDOWOfMonth(int weekNum, DayOfWeek DOW, DateTime beginDate, DateTime endDate)
{
List<DateTime> datesForNthDOWOfMonth = new List<DateTime>();
int earliestDayOfMonth = 1;
int latestDayOfMonth = 7;
DateTime currentDate = beginDate;
switch (weekNum)
{
case 1:
earliestDayOfMonth = 1;
latestDayOfMonth = 7;
break;
case 2:
earliestDayOfMonth = 8;
latestDayOfMonth = 14;
break;
case 3:
earliestDayOfMonth = 15;
latestDayOfMonth = 21;
break;
case 4:
earliestDayOfMonth = 22;
latestDayOfMonth = 28;
break;
}
while (currentDate < endDate)
{
DateTime dateToInc = currentDate;
DateTime endOfMonth = new DateTime(dateToInc.Year, dateToInc.Month, DateTime.DaysInMonth(dateToInc.Year, dateToInc.Month));
bool dateFound = false;
while (!dateFound)
{
dateFound = dateToInc.DayOfWeek.Equals(DOW);
if (dateFound)
{
if ((dateToInc.Day >= earliestDayOfMonth) &&
(dateToInc.Day <= latestDayOfMonth))
{
datesForNthDOWOfMonth.Add(dateToInc);
}
}
if (dateToInc.Date.Equals(endOfMonth.Date)) continue;
dateToInc = dateToInc.AddDays(1);
}
currentDate = new DateTime(currentDate.Year, currentDate.Month, 1);
currentDate = currentDate.AddMonths(1);
}
return datesForNthDOWOfMonth;
}
... y llámalo de esta manera:
// This is to get the 1st Monday in each month from today through one year from today
DateTime beg = DateTime.Now;
DateTime end = DateTime.Now.AddYears(1);
List<DateTime> dates = GetDatesForNthDOWOfMonth(1, DayOfWeek.Monday, beg, end);
// To see the list of dateTimes, for verification
foreach (DateTime d in dates)
{
MessageBox.Show(string.Format("Found {0}", d.ToString()));
}
Puedes obtener el segundo viernes de cada mes así:
List<DateTime> dates = GetDatesForNthDOWOfMonth(2, DayOfWeek.Friday, beg, end);
... etc.
La mayoría de las respuestas anteriores son parcialmente precisas o innecesariamente complejas. Puede probar esta función más simple, que también verifica si la fecha dada es la última, pero el día N del mes.
public static bool IsNthDayofMonth(this DateTime date, DayOfWeek weekday, int N)
{
if (N > 0)
{
var first = new DateTime(date.Year, date.Month, 1);
return (date.Day - first.Day)/ 7 == N - 1 && date.DayOfWeek == weekday;
}
else
{
var last = new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
return (last.Day - date.Day) / 7 == (Math.Abs(N) - 1) && date.DayOfWeek == weekday;
}
La respuesta es de este sitio web . Copie / pegue aquí en caso de que el sitio se pierda alguna vez.
public static DateTime FindTheNthSpecificWeekday(int year, int month,int nth, System.DayOfWeek day_of_the_week)
{
// validate month value
if(month < 1 || month > 12)
{
throw new ArgumentOutOfRangeException("Invalid month value.");
}
// validate the nth value
if(nth < 0 || nth > 5)
{
throw new ArgumentOutOfRangeException("Invalid nth value.");
}
// start from the first day of the month
DateTime dt = new DateTime(year, month, 1);
// loop until we find our first match day of the week
while(dt.DayOfWeek != day_of_the_week)
{
dt = dt.AddDays(1);
}
if(dt.Month != month)
{
// we skip to the next month, we throw an exception
throw new ArgumentOutOfRangeException(string.Format("The given month has less than {0} {1}s", nth, day_of_the_week));
}
// Complete the gap to the nth week
dt = dt.AddDays((nth - 1) * 7);
return dt;
}
Parece que el idioma proporciona los métodos de fecha / día para una fecha determinada. Si alguien estaba interesado, puede leer sobre la congruencia de Zeller .
No creo que eso sea lo que querían que hicieras, pero podrías encontrar el día de la semana del primer día de un mes a partir de ahí. Ahora que lo pensé, podrías encontrar el día de la semana para el día dado como N
y obtener ese módulo 7.
¡Oh, espera, es la enésima ocurrencia de un día de la semana (como el domingo) o como el décimo día de la semana del mes! De acuerdo, veo los ejemplos.
Tal vez haría la diferencia si pudieras construir una fecha como el 1 de un mes.
Dado que es la Octava ocurrencia de un día de la semana , y que no puede jugar con el tipo de datos de fecha y hora, y que tiene acceso tanto al día de la semana como a las funciones del día del mes. ¿Sería el domingo un cero?
1) Primero, el día de la semana debería coincidir con el día de la semana.
2) N tendría que ser al menos 1 y como máximo 4.
3) El día del mes oscilaría entre n * 7 * día de la semana + 1 y n * 7 * día de la semana + 6 para la misma n.
- Dejame pensar sobre eso. Si el domingo fue el primero ... 0 * 7 * 0 + 1 = 1 y el sábado 6 sería 0 * 7 * 0 + 6.
Creo que los puntos 1 y 3 anteriores son suficientes, ya que una función de obtención del día del mes no debería violar 2.
(* first try, this code sucks *)
function isNthGivenDayInMonth(date : dateTime;
dow : dayOfWeek;
N : integer) : boolean;
var B, A : integer (* on or before and after day of month *)
var Day : integer (* day of month *)
begin
B := (N-1)*7 + 1; A := (N-1)*7 + 6;
D := getDayOfMonth(date);
if (dow <> getDayOfWeek(date)
then return(false)
else return( (B <= Day) and (A >= Day) );
end; (* function *)
Espero que no haya un error en esa jaja!
[Editar: El sábado hubiera sido el 7º, y el límite superior anterior (N-1)*7 + 7
]
Su solución parece que coincidiría con 2 semanas diferentes? Parece que siempre regresaría a cero los domingos? Debería haber hecho un pseudocódigo en C # ... cortocircuito && es como mi if ... hey should not Sunday el primer partido para N = 1 en meses que comienzan el domingo?
d/ 7 == n
Eso daría como resultado (either 0 or 1)/7 == 1
, ¡eso no puede ser correcto! Tu ||
atrapa el (n-1)
también, Robert tiene eso. ¡Ve con la respuesta de Robert Wagner! ¡Son solo 2 líneas, el corto es bueno! Tener (Day-1) mod 7
[edit: (Day-1) div 7
] elimina mis variables innecesarias y 2 líneas de configuración.
Para que quede constancia, debería verificarse si hay casos límite, y qué pasa si el 31 de agosto era domingo o sábado.
[edit: Debería haber verificado el caso de fin de semana también. ¡Lo siento!]
Podría cambiar el control de la semana para que la función diga:
private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n){
int d = date.Day;
return date.DayOfWeek == dow && (d-1)/7 == (n-1);
}
Aparte de eso, se ve bastante bueno y eficiente.
Puede encontrar una función que devuelve una fecha para la enésima ocurrencia de un día de la semana en particular en cualquier mes.
Ver http://chiragrdarji.wordpress.com/2010/08/23/find-second-saturday-and-fourth-saturday-of-month/
Esto es lo que MSDN tiene que decir. Su VB, pero se traduce fácilmente.