Je dois connaître la date du premier et du dernier jour de la semaine en connaissant le numéro de la semaine.
Je reçois une date de début et une date de fin, représentant le premier et le dernier jour d'une semaine sélectionnée dans une année donnée. ensuite, je dois connaître la date de début et la date de fin de la même semaine de l'année précédente pour pouvoir comparer graphiquement certaines données.
J'ai réussi à obtenir le numéro de semaine en fonction de la date de début et de la date de fin indiquées. Maintenant, je dois connaître la date du premier et du dernier jour de la même semaine de l'année précédente. Comment pourrais-je faire cela le plus rapidement?
EDIT: Voici comment j'ai eu le numéro de la semaine:
private int GetWeekNumber(DateTime date)
{
GregorianCalendar calendar = new GregorianCalendar(GregorianCalendarTypes.USEnglish);
return calendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
}
Vous pouvez utiliser les deux méthodes suivantes pour calculer le numéro de semaine et la date de début d'un numéro de semaine donné en fonction d'une année donnée:
// this method is borrowed from http://stackoverflow.com/a/11155102/284240
public static int GetIso8601WeekOfYear(DateTime time)
{
DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
public static DateTime FirstDateOfWeek(int year, int weekOfYear, System.Globalization.CultureInfo ci)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = (int)ci.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;
DateTime firstWeekDay = jan1.AddDays(daysOffset);
int firstWeek = ci.Calendar.GetWeekOfYear(jan1, ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);
if ((firstWeek <= 1 || firstWeek >= 52) && daysOffset >= -3)
{
weekOfYear -= 1;
}
return firstWeekDay.AddDays(weekOfYear * 7);
}
Ensuite, vous pouvez obtenir les deux dates de la manière suivante:
// 46
int thisWeekNumber = GetIso8601WeekOfYear(DateTime.Today);
// 11/11/2013
DateTime firstDayOfWeek= FirstDateOfWeek(2013, thisWeekNumber, CultureInfo.CurrentCulture);
// 11/12/2012
DateTime firstDayOfLastYearWeek = FirstDateOfWeek(2012, thisWeekNumber, CultureInfo.CurrentCulture);
Ajoutez 6 jours pour obtenir la fin de la semaine.
Ceci est ma solution:
public static DateTime FirstDayOfWeek(DateTime date)
{
DayOfWeek fdow = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
int offset = fdow - date.DayOfWeek;
DateTime fdowDate = date.AddDays(offset);
return fdowDate;
}
public static DateTime LastDayOfWeek(DateTime date)
{
DateTime ldowDate = FirstDayOfWeek(date).AddDays(6);
return ldowDate;
}
La méthode ci-dessus calcule la première date erronée pour la 1ère semaine de 2016.
Code fixe basé sur les réponses précédentes
public DateTime FirstDateOfWeek(
int year,
int weekOfYear)
{
var newYear = new DateTime(year, 1, 1);
var weekNumber = newYear.GetIso8601WeekOfYear();
DateTime firstWeekDate;
if (weekNumber != 1)
{
var dayNumber = (int) newYear.DayOfWeek;
firstWeekDate = newYear.AddDays(7 - dayNumber + 1);
}
else
{
var dayNumber = (int)newYear.DayOfWeek;
firstWeekDate = newYear.AddDays(-dayNumber + 1);
}
if (weekOfYear == 1)
{
return firstWeekDate;
}
return firstWeekDate.AddDays(7 * (weekOfYear - 1));
}
Test plus
[TestCase(2016, 1, 2016, 1, 4)]
[TestCase(2016, 2, 2016, 1, 11)]
[TestCase(2016, 52, 2016, 12, 26)]
[TestCase(2014, 1, 2013, 12, 30)]
public void FirstDateOfWeek_ShouldReturnCorrectDay(int year, int weekNumber, int correctYear, int correctMonth, int correctDay)
{
var helper = new DateHelper();
var result = helper.FirstDateOfWeek(year, weekNumber);
Assert.That(result.Year, Is.EqualTo(correctYear));
Assert.That(result.Month, Is.EqualTo(correctMonth));
Assert.That(result.Day, Is.EqualTo(correctDay));
}
private static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
var firstDate = new DateTime(year, 1, 4);
//first thursday of the week defines the first week (https://en.wikipedia.org/wiki/ISO_8601)
//Wiki: the 4th of january is always in the first week
while (firstDate.DayOfWeek != DayOfWeek.Monday)
firstDate = firstDate.AddDays(-1);
return firstDate.AddDays((weekOfYear - 1)*7);
}
Solution plus simple et plus efficace!
Soustrayez 1 an de votre DateTime d'origine et appelez à nouveau votre méthode GetWeekNumber avec cela.
TimeSpan oneYear = dateTime.AddYears(1) - dateTime;
var lastYearWeekNumber = GetWeekNumber(dateTime.Subtract(oneYear));