2009-09-30 24 views

risposta

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

essere consapevoli che questo è nonISO 8601 compatibili. In Svezia si usa ISO 8601 week numeri, ma anche se la cultura è impostato su "sv-SE", CalendarWeekRule è FirstFourDayWeek, e FirstDayOfWeek è Lunedi il weekNo variabile sarà impostata su al posto del corretto in il codice sopra.

L'ho provato solo con le impostazioni svedesi ma sono abbastanza sicuro che tutti i paesi (Austria, Germania, Svizzera e altri) che utilizzano i numeri di settimana ISO 8601 saranno interessati da questo problema.

Peter van Ooijen e Shawn Steele ha diverse soluzioni a questo problema.

Ecco una soluzione compatta

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); 
} 

E 'stato testato per le seguenti date

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

Risposta molto bella. Grazie – roosteronacid

+0

lo stesso problema con il resto della scandinavia, penso, sono un danese e mi chiedevo perché i miei test mostrassero il 31/12 come settimana 53 anche perché il mio Google Calendar indicava la sua settimana # 1. – BerggreenDK

+0

perché usare "var" ovunque? – AndreaCi

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

qualcosa di simile ...

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

Partenza GetWeekOfYear su MSDN ha questo esempio:

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

So che questo è in ritardo, ma dal momento che è venuto nella mia ricerca ho pensato di gettare una diversa soluzione in. Questa era la soluzione aC#.

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

Restituisce "5" per la data 29/12/2016 - dovrebbe restituire 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; 

Funziona bene sia per le culture statunitensi che russe. Anche la ISO 8601 sarà corretta, perché la settimana russa inizia lunedì.

1

Se si desidera il numero di settimana ISO 8601, in cui le settimane iniziano con un lunedì, tutte le settimane sono sette giorni e la settimana 1 è la settimana che contiene il primo giovedì dell'anno, questa potrebbe essere una soluzione.

Dal momento che non sembra esserci una cultura .Net che produce il numero di settimana ISO-8601 corretto, dovrei ignorare completamente la determinazione della settimana integrata e fare il calcolo manualmente, invece di tentare di correggere un risultato parzialmente corretto.

Quello che ho finito con è il seguente metodo di estensione:

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

Innanzitutto, ((int) date.DayOfWeek + 6)% 7) determina il numero settimana, 0 = lunedi, 6 = domenica.

date.AddDays (- ((int) data.DayOfWeek + 6)% 7) determina la data del lunedì precedere il numero della settimana richiesta.

Tre giorni dopo è il giovedi bersaglio, che determina quale anno la settimana è in.

Se si divide il (base zero) il giorno numero entro l'anno per sette (arrotondato per difetto), si ottiene la (numero della settimana basato su zero nell'anno.

In C#, i risultati del calcolo dei numeri interi sono arrotondati implicitamente.

Problemi correlati