2009-09-30 22 views

Respuesta

72
var currentCulture = CultureInfo.CurrentCulture; 
var weekNo = currentCulture.Calendar.GetWeekOfYear(
       new DateTime(2013, 12, 31), 
       currentCulture.DateTimeFormat.CalendarWeekRule, 
       currentCulture.DateTimeFormat.FirstDayOfWeek); 

Tenga en cuenta que este es noISO 8601 compatibles. En Suecia se utiliza la norma ISO 8601 week números, pero a pesar de que la cultura se establece en "sv-SE", CalendarWeekRule es FirstFourDayWeek y FirstDayOfWeek es el lunes la weekNo variable se establece en en lugar de la correcta en el código anterior

Solo he intentado esto con la configuración sueca, pero estoy bastante seguro de que todos los países (Austria, Alemania, Suiza y más) que utilicen números semanales ISO 8601 se verán afectados por este problema.

y Shawn Steele tiene diferentes soluciones a este problema.

Aquí es una solución compacta

private static int WeekOfYearISO8601(DateTime date) 
{ 
    var day = (int)CultureInfo.CurrentCulture.Calendar.GetDayOfWeek(date); 
    return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date.AddDays(4 - (day == 0 ? 7 : day)), CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); 
} 

Ha sido probado para las siguientes fechas

var datesAndISO8601Weeks = new Dictionary<DateTime, int> 
         { 
          {new DateTime(2000, 12, 31), 52}, 
          {new DateTime(2001, 1, 1), 1}, 
          {new DateTime(2005, 1, 1), 53}, 
          {new DateTime(2007, 12, 31), 1}, 
          {new DateTime(2008, 12, 29), 1}, 
          {new DateTime(2010, 1, 3), 53}, 
          {new DateTime(2011, 12, 31), 52}, 
          {new DateTime(2012, 1, 1), 52}, 
          {new DateTime(2013, 1, 2), 1}, 
          {new DateTime(2013, 12, 31), 1}, 
         }; 

foreach (var dateWeek in datesAndISO8601Weeks) 
{ 
    Debug.Assert(WeekOfYearISO8601(dateWeek.Key) == dateWeek.Value, dateWeek.Key.ToShortDateString() + " should be week number " + dateWeek.Value + " but was " + WeekOfYearISO8601(dateWeek.Key)); 
} 
+1

Muy buena respuesta. Gracias – roosteronacid

+0

mismo problema con el resto de Escandinavia. Creo que soy danés y me preguntaba por qué mis pruebas mostraron que el 31/12 también era la semana 53, ya que mi Google Calender dice que es la semana # 1. – BerggreenDK

+0

¿por qué usar "var" en todas partes? – AndreaCi

1
My.Computer.Info.InstalledUICulture.DateTimeFormat.Calendar.GetWeekOfYear(yourDateHere, CalendarWeekRule.FirstDay, My.Computer.Info.InstalledUICulture.DateTimeFormat.FirstDayOfWeek) 

Algo como esto ...

4
public static int GetWeekNumber(DateTime dtPassed) 
    { 
      CultureInfo ciCurr = CultureInfo.CurrentCulture; 
      int weekNum = ciCurr.Calendar.GetWeekOfYear(dtPassed, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); 
      return weekNum; 
    } 
4

Salida GetWeekOfYear en MSDN tiene este ejemplo:

using System; 
using System.Globalization; 


public class SamplesCalendar { 

    public static void Main() { 

     // Gets the Calendar instance associated with a CultureInfo. 
     CultureInfo myCI = new CultureInfo("en-US"); 
     Calendar myCal = myCI.Calendar; 

     // Gets the DTFI properties required by GetWeekOfYear. 
     CalendarWeekRule myCWR = myCI.DateTimeFormat.CalendarWeekRule; 
     DayOfWeek myFirstDOW = myCI.DateTimeFormat.FirstDayOfWeek; 

     // Displays the number of the current week relative to the beginning of the year. 
     Console.WriteLine("The CalendarWeekRule used for the en-US culture is {0}.", myCWR); 
     Console.WriteLine("The FirstDayOfWeek used for the en-US culture is {0}.", myFirstDOW); 
     Console.WriteLine("Therefore, the current week is Week {0} of the current year.", myCal.GetWeekOfYear(DateTime.Now, myCWR, myFirstDOW)); 

     // Displays the total number of weeks in the current year. 
     DateTime LastDay = new System.DateTime(DateTime.Now.Year, 12, 31); 
     Console.WriteLine("There are {0} weeks in the current year ({1}).", myCal.GetWeekOfYear(LastDay, myCWR, myFirstDOW), LastDay.Year); 

    } 

} 
1

Sé que es tarde, pero desde que entró en mi búsqueda pensé que iba a lanzar una diferente solución en. Esta fue la solución de CA.

(int)(Math.Ceiling((decimal)startDate.Day/7)) + (((new DateTime(startDate.Year, startDate.Month, 1).DayOfWeek) > startDate.DayOfWeek) ? 1 : 0);   
+0

Esto devuelve "5" para la fecha 29/12/2016 - debe devolver 52 – DNKROZ

0

var cultureInfo = CultureInfo.CurrentCulture; var calendar = cultureInfo.Calendar;

 var calendarWeekRule = cultureInfo.DateTimeFormat.CalendarWeekRule; 
     var firstDayOfWeek = cultureInfo.DateTimeFormat.FirstDayOfWeek; 
     var lastDayOfWeek = cultureInfo.LCID == 1033 //En-us 
      ? DayOfWeek.Saturday 
      : DayOfWeek.Sunday; 

     var lastDayOfYear = new DateTime(date.Year, 12, 31); 

     //Check if this is the last week in the year and it doesn`t occupy the whole week 
     var weekNumber = calendar.GetWeekOfYear(date, calendarWeekRule, firstDayOfWeek); 
     return weekNumber == 53 && lastDayOfYear.DayOfWeek != lastDayOfWeek 
       ? 1 
       : weekNumber; 

Funciona bien para las culturas de EE. UU. Y Rusia. ISO 8601 también será correcto, porque la semana rusa comienza el lunes.

1

Si desea el número de semana ISO 8601, en que las semanas comienzan con un lunes, todas las semanas son de siete días, y la semana 1 es la semana que contiene el primer jueves de año, esta puede ser una solución.

Dado que no parece existir un .Net-culture que arroje el número correcto de la semana ISO-8601, calificaría el bypass en la determinación de la semana incorporada, y haré el cálculo manualmente, en lugar de intentar corregirlo un resultado parcialmente correcto.

Lo que terminé con es la siguiente método de extensión:

public static int GetIso8601WeekNumber(this DateTime date) 
{ var thursday = date.AddDays(3 - ((int)date.DayOfWeek + 6) % 7); 
    return 1 + (thursday.DayOfYear - 1)/7; 
} 

Primero de todo, ((int) date.DayOfWeek + 6)% 7) determina el número de la semana, 0 = Lunes, 6 = domingo.

date.AddDays (- ((int) date).DayOfWeek + 6)% 7) determina la fecha del lunes anterior al número de semana solicitado.

Tres días más tarde, es el Jueves de destino, que determina en qué año la semana está en.

Si se divide el (basado en cero) el día número dentro del año por siete (redondeando hacia abajo), se obtiene la (cero base) número de semana en el año.

En C#, los resultados del cálculo de enteros se redondean implícitamente.

Cuestiones relacionadas