Obtenga el número de semana correcto de una fecha determinada

Resuelto Amberlamps asked hace 12 años • 20 respuestas

Busqué mucho en Google y encontré muchas soluciones, pero ninguna me dio el número de semana correcto para el 31 de diciembre de 2012. Incluso el ejemplo en MSDN ( enlace ) falla.

2012-12-31 es lunes, por lo tanto debería ser la Semana 1, pero cada método que probé me da 53. Estos son algunos de los métodos que he probado:

De la biblioteca MDSN:

DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
Calendar cal = dfi.Calendar;

return cal.GetWeekOfYear(date, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);

Solución 2:

return new GregorianCalendar(GregorianCalendarTypes.Localized).GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

Solución 3:

CultureInfo ciCurr = CultureInfo.CurrentCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(dtPassed, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return weekNum;

Actualizar

El siguiente método en realidad devuelve 1 cuando la fecha es 2012-12-31. En otras palabras, mi problema era que mis métodos no seguían el estándar ISO-8601.

// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
    // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
    // be the same week# as whatever Thursday, Friday or Saturday are,
    // and we always get those right
    DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    // Return the week of our adjusted day
    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
Amberlamps avatar Jun 22 '12 17:06 Amberlamps
Aceptado

Como se indica en esta página de MSDN , existe una ligera diferencia entre la numeración de semanas ISO8601 y .Net.

Puede consultar este artículo en el Blog de MSDN para obtener una mejor explicación: " Formato de semana del año ISO 8601 en Microsoft .Net "

En pocas palabras, .Net permite dividir semanas en años, mientras que el estándar ISO no lo hace. En el artículo también hay una función sencilla para obtener el número de semana ISO 8601 correcto para la última semana del año.

Actualización El siguiente método en realidad devuelve 1, 2012-12-31que es correcto en ISO 8601 (por ejemplo, Alemania).

// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
    // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
    // be the same week# as whatever Thursday, Friday or Saturday are,
    // and we always get those right
    DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    // Return the week of our adjusted day
    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
} 
il_guru avatar Jun 22 '2012 11:06 il_guru

¡Buenas noticias! Se acaba de fusionar una solicitud de extracción que se agrega System.Globalization.ISOWeeka .NET Core y actualmente está programada para la versión 3.0. Con suerte, se propagará a otras plataformas .NET en un futuro no muy lejano.

El tipo tiene la siguiente firma, que debería cubrir la mayoría de las necesidades semanales ISO :

namespace System.Globalization
{
    public static class ISOWeek
    {
        public static int GetWeekOfYear(DateTime date);
        public static int GetWeeksInYear(int year);
        public static int GetYear(DateTime date);
        public static DateTime GetYearEnd(int year);
        public static DateTime GetYearStart(int year);
        public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek);
    }
}

Puedes encontrar el código fuente aquí .

ACTUALIZACIÓN : Estas API también se han incluido en la versión 2.1 de .NET Standard .

khellang avatar Jun 19 '2018 10:06 khellang

Un año puede tener más de 52 semanas. Cada año tiene 52 semanas completas + 1 o +2 (año bisiesto) días extra. Compensan una semana 53.

  • 52 semanas * 7 días = 364 días.

Entonces, por cada año tienes al menos un día adicional. Dos para los años bisiestos. ¿Estos días adicionales se cuentan como semanas independientes?

La cantidad de semanas que hay realmente depende del día de inicio de la semana. Consideremos esto para 2012.

  • EE. UU. (domingo -> sábado): 52 semanas + una semana corta de 2 días para 2012-12-30 y 2012-12-31. Esto da como resultado un total de 53 semanas. Los dos últimos días de este año (domingo + lunes) conforman su propia semana corta.

Verifique la configuración de su cultura actual para ver qué usa como primer día de la semana.

Como puede ver, es normal obtener 53 como resultado.

  • Europa (lunes -> domingo): el 2 de enero (2012-1-2) es el primer lunes, por lo que este es el primer día de la primera semana. Pregunte el número de semana del 1 de enero y le devolverán 52, ya que se considera parte de la semana pasada de 2011.

Incluso es posible tener una semana 54. Ocurre cada 28 años cuando el 1 de enero y el 31 de diciembre se tratan como semanas separadas. También debe ser un año bisiesto.

Por ejemplo, el año 2000 tuvo 54 semanas. El 1 de enero (sábado) fue el primer día de la semana y el 31 de diciembre (domingo) fue el segundo día de la semana.

var d = new DateTime(2012, 12, 31);
CultureInfo cul = CultureInfo.CurrentCulture;

var firstDayWeek = cul.Calendar.GetWeekOfYear(
    d,
    CalendarWeekRule.FirstDay,
    DayOfWeek.Monday);

int weekNum = cul.Calendar.GetWeekOfYear(
    d,
    CalendarWeekRule.FirstDay,
    DayOfWeek.Monday);

int year = weekNum == 52 && d.Month == 1 ? d.Year - 1 : d.Year;
Console.WriteLine("Year: {0} Week: {1}", year, weekNum);

Impresiones: Año: 2012 Semana: 54

Cambie CalendarWeekRule en el ejemplo anterior a FirstFullWeek o FirstFourDayWeek y obtendrá 53. Mantengamos el día de inicio en lunes, ya que estamos tratando con Alemania.

Entonces, la semana 53 comienza el lunes 31/12/2012, dura un día y luego se detiene.

53 es la respuesta correcta. Cambia la cultura a Alemania si quieres probarla.

CultureInfo cul = CultureInfo.GetCultureInfo("de-DE");
Christophe Geers avatar Jun 22 '2012 11:06 Christophe Geers