2010-03-31 121 views
25

鑑於我有生日/週年日期時間,如何確定日期是否在特定日期範圍內發生?例如,如何確定日期範圍內是否有生日或週年紀念

生日= 2000年1月2日
日期範圍= 12/25/2008 - 2009/1/3

我需要一種方法來確定日期時是否沒有發生過這個人的生日範圍 - 最好在C#中。

我第一次嘗試將生日DateTime的年份更改爲與日期範圍相匹配,然後檢查「新」生日DateTime是否在日期範圍的開始日期和結束日期之間......但是日期範圍跨越不同的年份,就像我上面的例子 - 我不得不添加一個討厭的if語句。有沒有更好的辦法?

+3

+1因爲這個問題是麻煩很多比它看起來! – NibblyPig 2010-03-31 14:31:20

+3

不要忘記,事情變得更狡猾的閏年:) – 2010-03-31 14:33:21

+0

實際上閏年不會有任何區別:) – NibblyPig 2010-03-31 14:40:37

回答

8

好吧,這裏是我的起飛

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; 
} 
2

我假設你的日期存儲在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 
} 
+2

我想你的意思是生日 =和<=。 – 2010-03-31 14:19:40

+0

我不確定這是OP在找什麼。他的情況涉及將生日值*轉換成*範圍(基於年份),以查看它是否落入範圍內或範圍之外。 – LBushkin 2010-03-31 14:22:35

+0

哎呀..不錯的地方@Mongus。 @davekaro可以將比較日期包括在內,如果他需要更改爲> =和<=(並且可能使用.Date忽略任何時間部分,如果需要的話) – Dexter 2010-03-31 14:23:32

1

您可以使用DateTime對象的DayOfYear屬性。

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

如果範圍是01/11/2008 - 01/03/2009,則會發生此錯誤。 – 2010-03-31 14:24:26

+0

是真的 - 也許他的情況會允許他使用這個 - 否則,看起來他回到了一個討厭的陳述。我認爲tanascius有正確的想法。 – Ray 2010-03-31 14:30:13

+0

如果該人不是在被測試的範圍之前出生,這將會失敗。檢查我的答案,找出可能的解決方案 – 2010-03-31 14:44:35

0
if (Birthday.Month >= DateRangeLower.Month && Birthday.Month <= DateRangeUpper.Month 
     && Birthday.Day>= DateRangeLower.Day && Birthday.Day<= DateRangeUpper.Day) { 
//Partytime... 
} 
+0

等一下,我認爲這是正確的答案,但它不是 - 如果你的日期範圍是1月1日到3月3日,而你的生日是6月2日,這段代碼將不起作用。 – NibblyPig 2010-03-31 14:26:29

+0

這是不正確的,但它很接近。您需要檢查月份,並且僅限於 Birthday.Month == DateRangeLower.Month或Birthday.Month == DateRangeUpper.Month,然後再檢查一天。 – 2010-03-31 14:32:37

+0

你們都對,謝謝。我的邏輯錯誤很少。 =) – chriszero 2010-04-01 06:40:01

1

這裏是我的解決方案。它使用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)); 
+0

downvote有什麼理由嗎?我想知道這段代碼中有何錯誤。請留下評論 – tanascius 2010-03-31 14:58:53

2

更新答案包括由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; 
} 
+0

我回來發佈這個解決方案,這是做到這一點的方法,基本上將您的輸入年份設置爲與搜索的下限相同。儘管在上述情況下,如果bday是1983 10 5,範圍是1985 10 6到1986 10 10,那麼你可能必須對上限做同樣的處理,因爲IF將在規格化的> = min部分失敗。 – NibblyPig 2010-03-31 14:43:35

+0

閏年會發生什麼?例如,「生日」是「29/02/1984」,「min」是「01/10/2005」? – LukeH 2010-03-31 14:48:31

+0

我不認爲這將適用於我在原始問題中提供的日期。使用我的日期,規範化的日期將是1/2/2008,這不是> =「min」(12/25/2008)。 – davekaro 2010-03-31 14:50:30

1

你的問題的關鍵是搞清楚年分配給生日,以其中確保您可以執行有效的範圍比較。

你有兩個與該範圍內的子情況,你需要處理:

  1. 的下界具有同年作爲UPPERBOUND
  2. 的下界具有從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); 
+0

如果這個人在2010年出生,這仍然會說他在這個範圍內有個生日。我提供了一個可能的解決方案,首先檢查一年,然後正常化生日比較。 – 2010-03-31 14:37:12

+0

你的DateTime構造函數是錯誤的。您的解決方案不匹配12/26/2000 – tanascius 2010-03-31 14:37:24

+0

例如,當'someBirthday'是'29/02/2008'和'upperBoundDate'是'25/03/2009'時會發生什麼? – LukeH 2010-03-31 14:39:08

0

你可能會是最好的畫一幅畫此。

問題是從根本上確定是否存在這樣的N,使得該人的N歲生日在該範圍內。

您可以採用一個基準線並以模數來計算日數,該模數將處理年度翻轉(但閏年可能會導致逐個錯誤)。

另一種可能使簡單表示形式的選擇是,由於生日在日曆線上形成一維網格,因此生日不在該範圍內,該範圍必須完全處於該人的生日之間年:即NOT(生日001 < RangeStart & & RangeEnd <生日Y2)。

通常,當我們進行這種分析時,整個月都是這樣,所以在五月份找到所有的生日都比較容易,比如拿到生日卡。

0

設置生日年= 2000年,從日至年= 2000,以及可追溯至2000年。如果以日期爲從日期的前,設置可追溯至2001年。

是惡作劇後,從上面:

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

將這項工作!

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; 
    } 
} 
1

我只是將所有的日期大紀元時間,然後做一個直接比較。

我發現這個轉換here,稍加修改

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; 
1

不同的答案,將所有日期以特定的一年。

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; 
} 
0

這其中要正確處理閏年:

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; 
} 
相關問題