Week numbers according to ISO8601






3.75/5 (4 votes)
/// /// Stuct for the ISO 8601 week date/// /// /// See:/// See:/// Algorithm:<see...
/// <summary> /// Stuct for the ISO 8601 week date /// </summary> /// <remarks> /// See:<see cref="http://en.wikipedia.org/wiki/ISO_8601"/> /// See:<see cref="http://en.wikipedia.org/wiki/ISO_week_date"/> /// Algorithm:<see cref="http://www.boyet.com/Articles/PublishedArticles/CalculatingtheISOweeknumb.html"/> /// </remarks> public struct t_IsoWeek { //------------------------------------------------------------------------- static readonly string d_WeekRangeError = string.Format("Week number must be between {0} and {1}", d_MinWeek, d_MaxWeek); static readonly string d_YearRangeError = string.Format("Year number must be between {0} and {1}", d_MinYear, d_MaxYear); //------------------------------------------------------------------------- const int d_MinWeek = 1; const int d_MaxWeek = 53; const int d_MinYear = 0; const int d_MaxYear = 9999; //------------------------------------------------------------------------- int m_Year; int m_Week; //------------------------------------------------------------------------- /// <summary> /// Create a ISO week form a year and a ISO week /// </summary> /// <param name="p_Year">Year</param> /// <param name="p_Week">ISO Week</param> public t_IsoWeek(int p_Year, int p_Week) { m_Year = d_MinYear; m_Week = d_MinYear; Year = p_Year; Week = p_Week; } //------------------------------------------------------------------------- /// <summary> /// Create a ISO week form a DateTime /// </summary> /// <param name="p_Date">Date</param> public t_IsoWeek(DateTime p_Date) { m_Year = d_MinYear; m_Week = d_MinYear; this = GetIsoWeek(p_Date); } //------------------------------------------------------------------------- /// <summary> /// Gets the ISO week number /// </summary> public int Week { get { return m_Week; } private set { if (value < d_MinWeek || value > d_MaxWeek) { throw new ArgumentOutOfRangeException("Week", value, d_WeekRangeError); } m_Week = value; } } //------------------------------------------------------------------------- /// <summary> /// Gets the year number /// </summary> public int Year { get { return m_Year; } private set { if (value < d_MinYear || value > d_MaxYear) { throw new ArgumentOutOfRangeException("Year", value, d_YearRangeError); } m_Year = value; } } //------------------------------------------------------------------------- /// <summary> /// Gets the last day (sunday) of the current week /// </summary> public DateTime EndOfOfWeek { get { return StartOfWeek.AddDays(6); } } //------------------------------------------------------------------------- /// <summary> /// Gets the first day (monday) of the current week /// </summary> public DateTime StartOfWeek { get { return GetIsoWeekOne(m_Year).AddDays((m_Week - 1) * 7); } } //------------------------------------------------------------------------- /// <summary> /// Returns true if the week consists of days in two different years. /// Example: 2008-12-29 is written "2009-W01-1" and /// 2010-01-03 is written "2009-W53-7" /// </summary> public bool SpreadsTwoYears { get { return StartOfWeek.Year != EndOfOfWeek.Year; } } //------------------------------------------------------------------------- /// <summary> /// ISO week notation /// </summary> /// <returns>{year}-W{week}</returns> public override string ToString() { return string.Format("{0:####}-W{1:##}", m_Year, m_Week); } //------------------------------------------------------------------------- #region Static //------------------------------------------------------------------------- public static t_IsoWeek GetIsoWeek(DateTime p_Date) { DateTime l_WeekOne; int l_Year = p_Date.Year; if (p_Date >= new DateTime(l_Year, 12, 29)) { l_WeekOne = GetIsoWeekOne(l_Year + 1); if (p_Date < l_WeekOne) { l_WeekOne = GetIsoWeekOne(l_Year); } else { l_Year++; } } else { l_WeekOne = GetIsoWeekOne(l_Year); if (p_Date < l_WeekOne) { l_WeekOne = GetIsoWeekOne(--l_Year); } } int l_Week = (p_Date - l_WeekOne).Days / 7 + 1; return new t_IsoWeek(l_Year, l_Week); } //------------------------------------------------------------------------- /// <summary> /// Returns the monday of ISO week 01. /// Note that this can be the in the year before the given year. /// </summary> /// <param name="p_Year">Year</param> /// <returns>Monday of ISO week 01</returns> private static DateTime GetIsoWeekOne(int p_Year) { // get the date for the 4-Jan for this year DateTime l_Date4Jan = new DateTime(p_Year, 1, 4); // get the ISO day number for this date 1==Monday, 7==Sunday int l_ISODay = GetIsoDayOfWeek(l_Date4Jan); // return the date of the Monday that is less than or equal // to this date return l_Date4Jan.AddDays(1 - l_ISODay); } //------------------------------------------------------------------------- /// <summary> /// Returns the day of week as an integer like ISO: /// Monday = 1, Sunday = 7 /// This to comensate the System.DayOfWeek enumeration that starts at 0 (sunday) /// </summary> /// <param name="p_Date">Date</param> /// <returns>1 to 7</returns> public static int GetIsoDayOfWeek(DateTime p_Date) { switch (p_Date.DayOfWeek) { case DayOfWeek.Monday: return 1; case DayOfWeek.Tuesday: return 2; case DayOfWeek.Wednesday: return 3; case DayOfWeek.Thursday: return 4; case DayOfWeek.Friday: return 5; case DayOfWeek.Saturday: return 6; case DayOfWeek.Sunday: return 7; default: throw new NotImplementedException("DayOfWeek"); } } //------------------------------------------------------------------------- #endregion }