156 votes

Calculer la date à partir du numéro de semaine

Quelqu'un connaît-il un moyen facile d'obtenir la date du premier jour de la semaine (lundi ici en Europe). Je connais l'année et le numéro de la semaine ? Je vais faire cela en C#.

0 votes

Fortement lié, peut-être en double : stackoverflow.com/questions/659183/

0 votes

295voto

Mikael Svenson Points 18243

J'ai eu des problèmes avec la solution de @HenkHolterman, même avec la correction de @RobinAndersson.

Une lecture de la norme ISO 8601 résout le problème de manière satisfaisante. Utilisez le premier jeudi comme cible et non le lundi. Le code ci-dessous fonctionnera également pour la semaine 53 de 2009.

public static DateTime FirstDateOfWeekISO8601(int year, int weekOfYear)
{
    DateTime jan1 = new DateTime(year, 1, 1);
    int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;

    // Use first Thursday in January to get first week of the year as
    // it will never be in Week 52/53
    DateTime firstThursday = jan1.AddDays(daysOffset);
    var cal = CultureInfo.CurrentCulture.Calendar;
    int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

    var weekNum = weekOfYear;
    // As we're adding days to a date in Week 1,
    // we need to subtract 1 in order to get the right date for week #1
    if (firstWeek == 1)
    {
        weekNum -= 1;
    }

    // Using the first Thursday as starting week ensures that we are starting in the right year
    // then we add number of weeks multiplied with days
    var result = firstThursday.AddDays(weekNum * 7);

    // Subtract 3 days from Thursday to get Monday, which is the first weekday in ISO8601
    return result.AddDays(-3);
}

3 votes

J'ai essayé presque toutes les solutions données ici, celle-ci est la seule qui fonctionne correctement pour moi en ce moment. Actuellement, nous sommes le 7 février 2012. Le numéro de la semaine est le 6. Ce code me donne correctement le 6 février comme date de début de la semaine. Les autres solutions m'ont toutes donné le 13 février, qui est en fait la date de début de la semaine n°7.

1 votes

Fonctionne comme un charme testé quelques données : pastebin.com/mfx8s1vq Tout fonctionne parfaitement ! Merci Mikael !

0 votes

Mon correctif était apparemment nul puisqu'il ne fonctionnait pas en 2013. Merci pour la bonne solution :)

53voto

Henk Holterman Points 153608

Note

La réponse ci-dessous utilise les règles du calendrier .NET. Elle ne promet pas la conformité à la norme ISO8601. Consultez d'autres réponses ici si vous en avez besoin. La numérotation des semaines est un désordre, essayez toujours de trouver les règles que vous devez suivre en premier.


Le code ci-dessous place correctement le début de la semaine 1, 2009 au 29-12-2008. La CalendarWeekRule devrait probablement être un paramètre.

Notez que le numéro de la semaine doit être >= 1.

static DateTime FirstDateOfWeek(int year, int weekNum, CalendarWeekRule rule)
{
    Debug.Assert(weekNum >= 1);

    DateTime jan1 = new DateTime(year, 1, 1);

    int daysOffset = DayOfWeek.Monday - jan1.DayOfWeek;
    DateTime firstMonday = jan1.AddDays(daysOffset);
    Debug.Assert(firstMonday.DayOfWeek == DayOfWeek.Monday);

    var cal = CultureInfo.CurrentCulture.Calendar;
    int firstWeek = cal.GetWeekOfYear(firstMonday, rule, DayOfWeek.Monday);

    if (firstWeek <= 1)
    {
        weekNum -= 1;
    }

    DateTime result = firstMonday.AddDays(weekNum * 7);

    return result;
}

6 votes

Je ne pense pas que ce soit tout à fait correct. Utilisation de CalendarWeekRule.FirstFourDayWeek et l'année 2006 et la semaine 32, la date correcte à renvoyer est 2006, 7 août. Mais il renvoie le 14 août. J'ai modifié l'appel GetWeekOfYear pour utiliser le premier lundi au lieu du premier janvier et cela semble fonctionner.

1 votes

Cela ne fonctionne pas correctement avec la règle du FirstDay ; avec cette règle, la semaine 1 doit toujours commencer le 1er janvier. Mais FirstDateOfWeek(2011, 1, CalendarWeekRule.FirstDay) retours 27 décembre 2010

3 votes

Il n'y a pas que les Mayas qui ont eu des problèmes avec 2012. Le code s'est mal comporté avec la première semaine de 2012, il a changé cal.GetWeekOfYear(jan1, rule, DayOfWeek.Monday) ; en cal.GetWeekOfYear(firstMonday, rule, DayOfWeek.Monday) ; ce qui l'a corrigé.

38voto

Thomas Points 319

J'aime la solution proposée par Henk Holterman. Mais pour être un peu plus indépendant de la culture, vous devez obtenir le premier jour de la semaine pour la culture actuelle (ce n'est pas toujours le lundi) :

using System.Globalization;

static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
  DateTime jan1 = new DateTime(year, 1, 1);

  int daysOffset = (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;

  DateTime firstMonday = jan1.AddDays(daysOffset);

  int firstWeek = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(jan1, CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek);

  if (firstWeek <= 1)
  {
    weekOfYear -= 1;
  }

  return firstMonday.AddDays(weekOfYear * 7);
}

0 votes

Je l'ai ajouté à Mannex, en tant que méthode d'extension de Calendar et DateTimeFormatInfo. J'ai également fait des références croisées avec cette réponse pour être crédité.

1 votes

Il ne fonctionne pas correctement sur ma machine. Il affiche une date avec 0010 au lieu de 2010. Je ne sais pas si c'est un problème dans .net framework ou dans cette fonction. Belle tentative, en tout cas...

6 votes

firstMonday est un mauvais nom de variable pour quelque chose qui pourrait ne pas être un lundi. =)

10voto

Jon Skeet Points 692016

Le plus simple est probablement de trouver le premier lundi de l'année, puis d'ajouter le nombre de semaines correspondant. Voici un exemple de code. Il suppose un numéro de semaine commençant à 1, soit dit en passant :

using System;

class Test
{
    static void Main()
    {
        // Show the third Tuesday in 2009. Should be January 20th
        Console.WriteLine(YearWeekDayToDateTime(2009, DayOfWeek.Tuesday, 3));
    }

    static DateTime YearWeekDayToDateTime(int year, DayOfWeek day, int week)
    {
        DateTime startOfYear = new DateTime (year, 1, 1);

        // The +7 and %7 stuff is to avoid negative numbers etc.
        int daysToFirstCorrectDay = (((int)day - (int)startOfYear.DayOfWeek) + 7) % 7;

        return startOfYear.AddDays(7 * (week-1) + daysToFirstCorrectDay);
    }
}

4 votes

Oui, mais le premier lundi de l'année pourrait appartenir à la semaine 52|53 de l'année précédente.

2 votes

Cela dépend de la façon dont vous voulez définir les choses. Malheureusement, nous n'avons pas beaucoup d'informations sur lesquelles nous appuyer... Mais j'espère que cela vous sera utile.

4voto

Alexander Kahoun Points 1632

Personnellement, je profiterais de l'information sur la culture pour obtenir le jour de la semaine et je bouclerais jusqu'au premier jour de la semaine de la culture. Je ne suis pas sûr de l'expliquer correctement, voici un exemple :

    public DateTime GetFirstDayOfWeek(int year, int weekNumber)
    {
        return GetFirstDayOfWeek(year, weekNumber, Application.CurrentCulture);
    }

    public DateTime GetFirstDayOfWeek(int year, int weekNumber,
        System.Globalization.CultureInfo culture)
    {
        System.Globalization.Calendar calendar = culture.Calendar;
        DateTime firstOfYear = new DateTime(year, 1, 1, calendar);
        DateTime targetDay = calendar.AddWeeks(firstOfYear, weekNumber);
        DayOfWeek firstDayOfWeek = culture.DateTimeFormat.FirstDayOfWeek;

        while (targetDay.DayOfWeek != firstDayOfWeek)
        {
            targetDay = targetDay.AddDays(-1);
        }

        return targetDay;
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X