我想知道有没有更好/更简单的方式来加载用户的生日。
我有一个User实例,它有属性,包括这个:
public DateTime? BirthDate { get; set; }
我想要做的是加载从一个日期到另一个日期的bday的用户:
public IEnumerable<User> LoadUsersByBirthday(DateTime from, DateTime into)
我不关心生日年,例如,如果我有3个生日用户:
LoadUsersByBirthday(new DateTime(2990, 3, 1), new DateTime(3013, 4, 15))
应该返回2个用户 - 第1和第3个。
我的方法如下:
public IEnumerable<User> LoadUsersByBirthday(DateTime from, DateTime into)
{
var days = DateTime.DaysInMonth(from.Year, from.Month);
var u1 = _unit.User.Load(u => ((DateTime) (u.BirthDate)).Month == from.Month
&& ((DateTime) (u.BirthDate)).Day >= from.Day
&& ((DateTime) (u.BirthDate)).Day <= days);
var u2 = _unit.User.Load(u => ((DateTime) (u.BirthDate)).Month > from.Month
&& ((DateTime) (u.BirthDate)).Month < into.Month);
var u3 = _unit.User.Load(u => ((DateTime) (u.BirthDate)).Month == into.Month
&& ((DateTime) (u.BirthDate)).Day <= into.Day);
return u1.Concat(u2).Concat(u3);
}
它有效,但有更好/更简单的方法吗?
答案 0 :(得分:3)
由于闰年引起的问题以及生日实际上是闰日的人,这比预期更难解决。
最后,我记得我已经有一种方法可以准确计算出某人的年龄,计算闰年和闰年的生日。
鉴于这种方法,确定某人是否有生日给出一系列日期是微不足道的:
首先,计算他们的年龄 BEFORE 范围的开始。 接下来,计算范围结束时的年龄。
如果计算的年龄不同,那么他们必须在指定的范围内过生日。
全部放在一起:
public IEnumerable<User> UsersByBirthday(IEnumerable<User> users, DateTime from, DateTime to)
{
if (to < from)
throw new ArgumentException("'from' must be at or before 'to'.");
return users.Where(user => IsBirthdayInRange(user.BirthDate, from, to));
}
public bool IsBirthdayInRange(DateTime birthday, DateTime from, DateTime to)
{
if (to < from)
throw new ArgumentException("'from' must be at or before 'to'.");
if (birthday > from)
throw new ArgumentException("'from' must be after 'birthday'");
return AgeInYears(birthday, from.AddDays(-1)) < AgeInYears(birthday, to);
}
/// <summary>Returns a person's age in years, accounting for leap years.</summary>
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;
}
这是闰日生日的一个小测试:
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));
使用您的_unit.User.Load()
:
public IEnumerable<User> LoadUsersByBirthday(DateTime from, DateTime into)
{
return _unit.User.Load(u => IsBirthdayInRange(u.Birthdate, from, into));
}
[编辑]
在非闰年处理闰日生日有两种可能性:将其视为2月28日,或将其视为3月1日。
上面的代码将其视为3月1日(根据英国法规)。如果您想参与处理,可以将leapDayMapsToFeb28
参数添加到IsBirthdayInRange()
,如下所示:
public bool IsBirthdayInRange(DateTime birthday, DateTime from, DateTime to, bool leapDayMapsToFeb28)
{
if (to < from)
throw new ArgumentException("'from' must be at or before 'to'.");
if (birthday > from)
throw new ArgumentException("'from' must be after 'birthday'");
if (leapDayMapsToFeb28 && (birthday.Month == 2) && (birthday.Day == 29) && !DateTime.IsLeapYear(from.Year))
birthday = new DateTime(birthday.Year, birthday.Month, 28);
return AgeInYears(birthday, from.AddDays(-1)) < AgeInYears(birthday, to);
}
答案 1 :(得分:2)
我认为这应该有效:
public IEnumerable<User> UsersByBirthday(IEnumerable<User> users, DateTime from, DateTime to)
{
var fromNormalized = NormalizeDate(from);
var intoNormalized = NormalizeDate(into);
return users.Where(u => fromNormalized <= NormalizeDate(u.BirthDate) && NormalizeDate(u.BirthDate) <= intoNormalized);
}
public int NormalizeDate(DateTime date)
{
return date.Month * 100 + date.Day;
}
NormalizeDate()
方法返回一个整数值,表示容易与之比较的月和日。 9月3日返回903,4月24日返回424。
如果from > to
没有错误处理。
答案 2 :(得分:1)
您可以将DateTime转换为Ticks并进行比较。
类似代码的东西(没有VS附近可能是语法错误)
DateTime from=new DateTime(...);
DateTime into=new DateTime(...);
IList<User> allUsers=...
固定:
IList<User> foundedUsers=allUsers.Where(user=> (new DateTime(1900, user.Birthday.Month, user.Birthday.Day)>new DateTime(1900,from.Month,from,Day)) && ...).ToList();
答案 3 :(得分:1)
假设第一天是birthday1(y1,m1,d1),第二天是birthday2(y2,m2,d2),那么你可以使用它:
diff = 31 * (m2 - m1) + (d2 - d1)
因为-31 < d2 - d1 < 31
,所以如果m2 - m1 > 0
,那么无论d2或d1是什么,结果都是差异&gt; 0; m2 - m1 < 0
,diff < 0
时的情况相同;当m2 == m1
时,diff的值范围仅在d2和d1上消失。实际上,31可以替换为任何更大的数字31,如32。