如何确定日期范围内是否发生了生日或周年纪念日

鉴于我有生日/周年纪念日期时间,如何确定该日期是否在特定日期范围内发生? 例如,

生日= 1/2/2000
日期范围= 12/25/2008 – 1/3/2009

我需要一种方法来确定这个人的生日是否发生在该日期范围内 – 最好是在C#中。

我首先要改变生日DateTime的年份以匹配日期范围,然后检查“新”生日DateTime是否在日期范围的开始日期和结束日期之间…但是当日期范围跨越不同年份时,就像我上面的例子 – 我不得不添加一个讨厌的if语句。 有没有更好的方法?

好的,这是我的看法

public static bool IsBirthDayInRange(DateTime birthday, DateTime start, DateTime end) { DateTime temp = birthday.AddYears(start.Year - birthday.Year); if (temp < start) temp = temp.AddYears(1); return birthday <= end && temp >= start && temp <= end; } 

我假设您的日期存储在DateTime变量中? 如果是这样,比较非常简单:

 if (Birthday > DateRangeLower && Birthday < DateRangeUpper) { // it's your birthday! } 

如果您愿意,可以将其封装在扩展方法中:

 public static bool Between(this DateTime compareDate, DateTime startDate, DateTime endDate) { return compareDate > startDate && compareDate < endDate; } 

然后你可以这样称呼它:

 if (Birthday.Between(DateRangeLower, DateRangeUpper) { // it's your birthday } 

更新 :如果您想忽略生日年份部分以确定日期的周年是否在范围内,请应用以下内容:

 if (DateRangeLower.DayOfYear <= DateRangeUpper.DayOfYear && Birthday.DayOfYear > DateRangeLower.DayOfYear && Birthday.DayOfYear < DateRangeUpper.DayOfYear) { // it's your birthday // the days are within the date range (and the range is in a single year) } else if (DateRangeLower.DayOfYear > DateRangeUpper.DayOfYear && Birthday.DayOfYear < DateRangeLower.DayOfYear && Birthday.DayOfYear > DateRangeUpper.DayOfYear) { // it's your birthday // note, we're actually checking to see if the date is outside of the // original date's days to handle the case where the dates span a year end boundary // this only works if the dates are not more than 1 year apart } 

更新的答案包括SLC提到的上限标准化。 这适用于该人在29/02年出生的情况。

 DateTime birthday = new DateTime(2000, 2, 1); DateTime min = new DateTime(2008, 12, 25); DateTime max = new DateTime(2009, 3, 1); DateTime nLower = new DateTime(min.Year, birthday.Month, birthday.Day); DateTime nUpper = new DateTime(max.Year, birthday.Month, birthday.Day); if (birthday.Year <= max.Year && ((nLower >= min && nLower <= max) || (nUpper >= min && nUpper <= max))) { // Happy birthday Console.WriteLine("Happy birthday"); } 

现在这个版本可以处理当天出生的人(29/02):

 public static bool IsBirthdayInRange( DateTime birthday, DateTime min, DateTime max) { var dates = new DateTime[] { birthday, min }; for (int i = 0; i < dates.Length; i++) { if (dates[i].Month == 2 && dates[i].Day == 29) { dates[i] = dates[i].AddDays(-1); } } birthday = dates[0]; min = dates[1]; DateTime nLower = new DateTime(min.Year, birthday.Month, birthday.Day); DateTime nUpper = new DateTime(max.Year, birthday.Month, birthday.Day); if (birthday.Year <= max.Year && ((nLower >= min && nLower <= max) || (nUpper >= min && nUpper <= max))) { return true; } return false; } 

您可以使用DateTime对象的DayOfYear属性。

 if ((birthday.DayOfYear >= start.DayOfYear) && (birthday.DayOfYear <= end.DayOfYear)) { ... } 

您的问题的关键在于确定要分配给生日的年份,以确保您可以执行有效的范围比较。

您有两个与您需要处理的范围相关的子类:

  1. LowerBound与UpperBound的年份相同
  2. LowerBound与UpperBound有不同的年份

编辑:咖啡不够。 忽略我之前的回答。

您需要根据您正在检查的生日的月份/日来调整日期。

您不能总是使用上限年份,因为生日可能会落入大于上限月份的月份。 一个简单的替代方案是执行两次检查:一次使用上限年份,然后再次使用前一年。 这处理年份边界的情况:

 var birthday = DateTime.Parse( "1/2/2000" ); var lowerBound = DateTime.Parse( "12/25/2008" ); var upperBound = DateTime.Parse( "1/3/2009" ); var adjustA = new Birthday( upperBound.Year, birthday.Month, birthday.Day ); var adjustB = adjustA.AddYears( -1 ); var isInBounds = (adjustA >= lowerBound && adjustA <= upperBound) || (adjustB >= lowerBound && adjustB <= upperBound); 

这是我的解决方案。 它使用DayOfYear来查找匹配项。 但是,如果开始日期的DayOfYear超过了结束日期的DayOfYear ,则必须小心。 我假设,开始日期早于结束日期:

 private static bool HasBirthDay( DateTime birthday, DateTime start, DateTime end ) { Debug.Assert( start < end ); if( start.DayOfYear < end.DayOfYear ) { if( birthday.DayOfYear > start.DayOfYear && birthday.DayOfYear < end.DayOfYear ) { return true; } } else { if( birthday.DayOfYear < end.DayOfYear || birthday.DayOfYear > start.DayOfYear ) { return true; } } return false; } // DayOfYear(start date) > DayOfYear(end date) var start = new DateTime( 2008, 12, 25 ); var end = new DateTime( 2009, 1, 3 ); Debug.Assert( HasBirthDay( new DateTime( 2000, 1, 2 ), start, end ) ); Debug.Assert( HasBirthDay( new DateTime( 2000, 12, 26), start, end ) ); Debug.Assert( !HasBirthDay( new DateTime( 2000, 1, 5 ), start, end ) ); Debug.Assert( !HasBirthDay( new DateTime( 2000, 12, 24 ), start, end ) ); // DayOfYear(start date) < DayOfYear(end date) start = new DateTime( 2008, 10, 25 ); end = new DateTime( 2008, 11, 3 ); Debug.Assert( HasBirthDay( new DateTime( 2000, 10, 26 ), start, end ) ); Debug.Assert( !HasBirthDay( new DateTime( 2000, 12, 5 ), start, end ) ); Debug.Assert( !HasBirthDay( new DateTime( 2000, 1, 24 ), start, end ) ); 

我只是将所有日期转换为大纪元时间,然后进行直接比较。

我在这里发现了这个转换,略有修改

 int epoch = (int)({Beginning/Ending Date} - new DateTime(1970, 1, 1)).TotalSeconds; 

所以你的整个代码就是这样

 int StartDateInEpoch = (int)(StartDate - new DateTime(1970, 1, 1)).TotalSeconds; int EndDateInEpoch = (int)(EndDate - new DateTime(1970, 1, 1)).TotalSeconds; int TargetDateInEpoch = (int)(TargetDate - new DateTime(1970, 1, 1)).TotalSeconds; if (StartDateInEpoch < TargetDateInEpoch && TargetDateInEpoch <= EndDateInEpoch) return true; 

一个不同的答案,将所有日期移动到特定年份。

 public static bool IsBirthDayInRange(DateTime birthday, DateTime start, DateTime end) { // This could be any date... var epoch = new DateTime(1970, 1, 1); // Start date is always epoch, end date is epoch + range span DateTime endDateInEpoch = epoch.AddSeconds((end - start).TotalSeconds); // Move the bithday back to epoch.Year DateTime birthDayInEpoch = birthday.AddYears(epoch.Year - birthday.Year); return birthday <= end && epoch < birthDayInEpoch && birthDayInEpoch <= endDateInEpoch; } 
 if (Birthday.Month >= DateRangeLower.Month && Birthday.Month <= DateRangeUpper.Month && Birthday.Day>= DateRangeLower.Day && Birthday.Day<= DateRangeUpper.Day) { //Partytime... } 

你可能最好为此画一幅画。

问题在于从根本上确定是否存在这样的N,使得该人的第N个生日位于该范围内。

您可以使用基线并使用模数进行日数计算,该模数将处理年份翻转(但是闰年可能会导致一个错误)。

可能使更简单表示的另一种选择是,由于生日在日历行上形成1-D网格,对于不在该范围内的生日,范围必须完全位于该人的连续几年的生日之间:即NOT (BirthdayY1

通常情况下,当我们进行这种分析时,整整几个月都是如此,所以在5月份找到所有生日,例如获得生日贺卡要简单得多。

将生日设置为年份= 2000,从日期到年份= 2000,将日期设置为2000年。如果到日期起始日期之前 ,则将日期设置为2001年。

之后的恶作剧,从上面:

 if (Birthday > DateRangeLower && Birthday < DateRangeUpper) { // it's your birthday! } 

这会工作!!!

 for(int i = startDate.year; i <= endDate.year; i++) { DateTime newBD = new DateTime(i, BD.month, BD.day); if((DateTime.Compare(newBD, startDate) >= 0) && (DateTime.Compare(newBD, endDate) <= 0)) { //gotcha break; } } 

这个应该正确处理闰年:

 public static bool IsBirthdayInRange(DateTime birthday, DateTime from, DateTime to) { if (to < from) { throw new ArgumentException("The specified range is not valid"); } int year = from.Year; int month = birthday.Month; int day = birthday.Day; if (from.DayOfYear > to.DayOfYear && birthday.DayOfYear < from.DayOfYear) { year++; } if (month == 2 && day == 29 && !DateTime.IsLeapYear(year)) { // Assuming people born on February 29 celebrate their birthday // one day earlier on non-leap years day--; } DateTime bDate = new DateTime(year, month, day); return bDate >= from.Date && bDate <= to.Date; }