Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This was harder to solve than expected, due to the problems caused by leap years and people who's birthdays are actually on a leap day.</p> <p>Finally, I remembered I had already a method that calculates someone's age in years accurately, accounting for leap years and birthdays that occur on a leap year.</p> <p>Given such a method, it's trivial to determine if someone has a birthday give a range of dates:</p> <p>First, calculate their age one day <em>BEFORE</em> the start of the range. Next, calculate their age at the end of the range.</p> <p>If the calculated ages differ, then they must have had a birthday in the specified range.</p> <p>Putting it all together:</p> <pre><code>public IEnumerable&lt;User&gt; UsersByBirthday(IEnumerable&lt;User&gt; users, DateTime from, DateTime to) { if (to &lt; from) throw new ArgumentException("'from' must be at or before 'to'."); return users.Where(user =&gt; IsBirthdayInRange(user.BirthDate, from, to)); } public bool IsBirthdayInRange(DateTime birthday, DateTime from, DateTime to) { if (to &lt; from) throw new ArgumentException("'from' must be at or before 'to'."); if (birthday &gt; from) throw new ArgumentException("'from' must be after 'birthday'"); return AgeInYears(birthday, from.AddDays(-1)) &lt; AgeInYears(birthday, to); } /// &lt;summary&gt;Returns a person's age in years, accounting for leap years.&lt;/summary&gt; public static int AgeInYears(DateTime birthday, DateTime today) { // See here for why this works: // http://social.msdn.microsoft.com/Forums/en-US/ba4a98af-aab3-4c59-bdee-611334e502f2/calculate-age-with-a-single-line-of-code-c return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372; } </code></pre> <p>Here's a little test for a leap day birthday:</p> <pre><code>DateTime test = new DateTime(2004, 2, 29); // Leap day. var start = new DateTime(2005, 3, 1); var end = new DateTime(2005, 6, 7); Console.WriteLine(IsBirthdayInRange(test, start, end)); </code></pre> <hr> <p>Using your <code>_unit.User.Load()</code>:</p> <pre><code>public IEnumerable&lt;User&gt; LoadUsersByBirthday(DateTime from, DateTime into) { return _unit.User.Load(u =&gt; IsBirthdayInRange(u.Birthdate, from, into)); } </code></pre> <hr> <p>[EDIT]</p> <p>There are two possibilities for handling a leap day birthday in a non-leap year: Treat it as Feb 28th, or treat it as Mar 1st. </p> <p>The code above treats it as Mar 1st (as per UK regulations). If you want to parameterise the handling, you can add a <code>leapDayMapsToFeb28</code> parameter to <code>IsBirthdayInRange()</code> as follows:</p> <pre><code>public bool IsBirthdayInRange(DateTime birthday, DateTime from, DateTime to, bool leapDayMapsToFeb28) { if (to &lt; from) throw new ArgumentException("'from' must be at or before 'to'."); if (birthday &gt; from) throw new ArgumentException("'from' must be after 'birthday'"); if (leapDayMapsToFeb28 &amp;&amp; (birthday.Month == 2) &amp;&amp; (birthday.Day == 29) &amp;&amp; !DateTime.IsLeapYear(from.Year)) birthday = new DateTime(birthday.Year, birthday.Month, 28); return AgeInYears(birthday, from.AddDays(-1)) &lt; AgeInYears(birthday, to); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload