给定一个生日/纪念日的日期时间,如何确定该日期是否发生在特定的日期范围内?例如,
生日日期 = 2000年1月2日
日期范围 = 2008年12月25日 - 2009年1月3日
我需要一种方法来确定这个人的生日是否发生在该日期范围内,最好是用C#。
我最初尝试将生日日期的年份更改为与日期范围相同的年份,然后只需检查"新"生日日期是否在日期范围的开始和结束日期之间......但当日期范围跨越不同的年份时,就像上面的例子一样,我不得不添加一个复杂的 if 语句。难道没有更好的方法吗?
给定一个生日/纪念日的日期时间,如何确定该日期是否发生在特定的日期范围内?例如,
生日日期 = 2000年1月2日
日期范围 = 2008年12月25日 - 2009年1月3日
我需要一种方法来确定这个人的生日是否发生在该日期范围内,最好是用C#。
我最初尝试将生日日期的年份更改为与日期范围相同的年份,然后只需检查"新"生日日期是否在日期范围的开始和结束日期之间......但当日期范围跨越不同的年份时,就像上面的例子一样,我不得不添加一个复杂的 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;
}
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提到的上限规范化。这对于那些非2月29日出生的人应该有效。
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;
}
birthday
是 29/02/1984
而 min
是 01/10/2005
时会怎样? - LukeH这是我的解决方案。它使用 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 ) );
你的问题的关键是确定要分配给生日哪一年,以确保您可以执行有效的范围比较。
您需要处理与所需范围相关的两个子情况:
编辑:没有喝足够的咖啡。请忽略我的先前答案。
您需要根据正在检查的生日的月/日调整日期。
您不能总是使用上限年份,因为生日可能会落在大于上限月份的月份中。一个简单的替代方法是进行两次检查:一次使用上限年份,然后再次使用前一年的年份。这处理了年度边界的情况:
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);
someBirthday
是 29/02/2008
而 upperBoundDate
是 25/03/2009
时会发生什么? - LukeH我会将所有日期转换为Epoch时间,然后进行直接比较。
我在这里找到了这个转换方法,稍作修改。
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.DayOfYear >= start.DayOfYear) && (birthday.DayOfYear <= end.DayOfYear)) {
...
}
if (Birthday.Month >= DateRangeLower.Month && Birthday.Month <= DateRangeUpper.Month
&& Birthday.Day>= DateRangeLower.Day && Birthday.Day<= DateRangeUpper.Day) {
//Partytime...
}
将生日设置为2000年,将起始日期设置为2000年,将结束日期设置为2000年。如果结束日期在起始日期之前,则将结束日期设置为2001年。
在完成上述操作后:
if (Birthday > DateRangeLower && Birthday < DateRangeUpper) {
// it's your birthday!
}