Click here to Skip to main content
Click here to Skip to main content
Alternative Tip

Week numbers according to ISO8601

, 30 Jul 2010
Rate this:
Please Sign up or sign in to vote.
/// /// Stuct for the ISO 8601 week date/// /// /// See:/// See:/// Algorithm:<see...
<pre lang="xml">/// <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
}
 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

jasper.mandos

Germany Germany
No Biography provided

Comments and Discussions

 
GeneralIt's not an "improvement" on your code, It's a user-friendly... Pinmemberjasper.mandos1-Aug-10 7:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140709.1 | Last Updated 30 Jul 2010
Article Copyright 2010 by jasper.mandos
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid