在 C# 中查找下一个日期
Find next occurrence of a date in C#
我想将按月和日标识的日期解析为将来发生的有效 DateTime
。
假设今天是 2023-05-06
,下面是一个 table 的输入和输出值:
Input
Output
06-24
2023-06-24
01-05
2024-01-05
02-29
2024-02-29
实现此目的的一种天真的方法是测试对 Year
部分使用 DateTime.Now.Year
是否会产生未来的日期:
var today = DateTime.Now;
bool dateInFuture = new DateTime(today.Year, 02, 29)).CompareTo(today);
但是您可能已经注意到这会导致异常,因为 2023-02-29
不是有效日期。
理想情况下,如果日期实际上无效,我希望这段代码能够计算出来,所以如果 00-46
作为输入传递,它可以告诉我那不是真实的日期,但那是有点棘手,因为我当前的实施因实际有效的日期而失败。
这可能有帮助:
var input = "02-29";
var year = DateTime.Today.Year;
if (DateTime.TryParse($"{year}-{input}", out DateTime date))
{
var isFutureDate = date > DateTime.Now;
}
else
{
// TODO: Manage error
}
您可以为此定义一个方法:
public static bool TryGetDate(string input, out DateTime date)
{
var year = DateTime.Today.Year;
if (input == "02-29")
{
while (!DateTime.IsLeapYear(year))
{
year++;
}
}
if (DateTime.TryParse($"{year}-{input}", out date))
{
if (date < DateTime.Now)
{
date = date.AddYears(1);
}
return true;
}
return false;
}
并使用它:
var input = "02-29";
if (TryGetDate(input, out DateTime date))
{
// ...
}
else
{
// TODO: Manage error
}
您可以使用 DateTime.IsLeapYear(year)
- 如 this answer in conjuction with DateTime.TryParse 所示,检查要转换的值是否为有效的日期时间:
您可以在 dotnetfiddle.net 中测试此代码:
DateTime today = DateTime.Now;
Int32 year = DateTime.IsLeapYear(today.Year) ? today.Year : today.AddYears(-2).Year;
DateTime tempDate = DateTime.Now;
// String is concatenated in "yyyy-MM-dd" format:
if (!DateTime.TryParse(year.ToString() + "-02-29", out tempDate))
{
// Date is not valid.
Console.WriteLine("Date (" + year.ToString() + "-02-29" + ") is not valid");
}
else
{
// Date with "yyyy-MM-dd" format:
Console.WriteLine("Date is valid: " + tempDate.ToString("yyyy-MM-dd"));
}
这是我的看法:
DateTime? GetFutureDateFromMonthDay(DateTime today, string monthDay) =>
Enumerable
.Range(today.Year, 9)
.Select(y => DateTime.TryParse($"{y}-{monthDay}", out DateTime result) ? (DateTime?)result : null)
.Where(x => x != null)
.Where(x => x > today)
.FirstOrDefault();
请注意,它向前看 9 年,因为闰年之间可能有 8 年的差距,并且您想确保获得未来的日期,因此可能需要再过一年。将 today
更改为 new DateTime(2096, 5, 6)
显示了该问题。
因此,鉴于此输入:
var today = new DateTime(2023, 5, 6);
var data = new[]
{
new { input = "06-24", output = (DateTime?)new DateTime(2023, 6, 24) },
new { input = "01-05", output = (DateTime?)new DateTime(2024, 1, 5) },
new { input = "02-29", output = (DateTime?)new DateTime(2024, 2, 29) },
new { input = "00-46", output = (DateTime?)null },
};
我运行这个查询:
var query =
from d in data
let expected = d.output
let actual = GetFutureDateFromMonthDay(today, d.input)
select new
{
d.input,
expected,
actual,
check = actual == expected,
};
我得到这个结果:
如果继续尝试 new DateTime(2096, 5, 6)
我现在明白了:
此代码生成未来日期或 returns null
以指示输入错误。
我想将按月和日标识的日期解析为将来发生的有效 DateTime
。
假设今天是 2023-05-06
,下面是一个 table 的输入和输出值:
Input | Output |
---|---|
06-24 |
2023-06-24 |
01-05 |
2024-01-05 |
02-29 |
2024-02-29 |
实现此目的的一种天真的方法是测试对 Year
部分使用 DateTime.Now.Year
是否会产生未来的日期:
var today = DateTime.Now;
bool dateInFuture = new DateTime(today.Year, 02, 29)).CompareTo(today);
但是您可能已经注意到这会导致异常,因为 2023-02-29
不是有效日期。
理想情况下,如果日期实际上无效,我希望这段代码能够计算出来,所以如果 00-46
作为输入传递,它可以告诉我那不是真实的日期,但那是有点棘手,因为我当前的实施因实际有效的日期而失败。
这可能有帮助:
var input = "02-29";
var year = DateTime.Today.Year;
if (DateTime.TryParse($"{year}-{input}", out DateTime date))
{
var isFutureDate = date > DateTime.Now;
}
else
{
// TODO: Manage error
}
您可以为此定义一个方法:
public static bool TryGetDate(string input, out DateTime date)
{
var year = DateTime.Today.Year;
if (input == "02-29")
{
while (!DateTime.IsLeapYear(year))
{
year++;
}
}
if (DateTime.TryParse($"{year}-{input}", out date))
{
if (date < DateTime.Now)
{
date = date.AddYears(1);
}
return true;
}
return false;
}
并使用它:
var input = "02-29";
if (TryGetDate(input, out DateTime date))
{
// ...
}
else
{
// TODO: Manage error
}
您可以使用 DateTime.IsLeapYear(year)
- 如 this answer in conjuction with DateTime.TryParse 所示,检查要转换的值是否为有效的日期时间:
您可以在 dotnetfiddle.net 中测试此代码:
DateTime today = DateTime.Now;
Int32 year = DateTime.IsLeapYear(today.Year) ? today.Year : today.AddYears(-2).Year;
DateTime tempDate = DateTime.Now;
// String is concatenated in "yyyy-MM-dd" format:
if (!DateTime.TryParse(year.ToString() + "-02-29", out tempDate))
{
// Date is not valid.
Console.WriteLine("Date (" + year.ToString() + "-02-29" + ") is not valid");
}
else
{
// Date with "yyyy-MM-dd" format:
Console.WriteLine("Date is valid: " + tempDate.ToString("yyyy-MM-dd"));
}
这是我的看法:
DateTime? GetFutureDateFromMonthDay(DateTime today, string monthDay) =>
Enumerable
.Range(today.Year, 9)
.Select(y => DateTime.TryParse($"{y}-{monthDay}", out DateTime result) ? (DateTime?)result : null)
.Where(x => x != null)
.Where(x => x > today)
.FirstOrDefault();
请注意,它向前看 9 年,因为闰年之间可能有 8 年的差距,并且您想确保获得未来的日期,因此可能需要再过一年。将 today
更改为 new DateTime(2096, 5, 6)
显示了该问题。
因此,鉴于此输入:
var today = new DateTime(2023, 5, 6);
var data = new[]
{
new { input = "06-24", output = (DateTime?)new DateTime(2023, 6, 24) },
new { input = "01-05", output = (DateTime?)new DateTime(2024, 1, 5) },
new { input = "02-29", output = (DateTime?)new DateTime(2024, 2, 29) },
new { input = "00-46", output = (DateTime?)null },
};
我运行这个查询:
var query =
from d in data
let expected = d.output
let actual = GetFutureDateFromMonthDay(today, d.input)
select new
{
d.input,
expected,
actual,
check = actual == expected,
};
我得到这个结果:
如果继续尝试 new DateTime(2096, 5, 6)
我现在明白了:
此代码生成未来日期或 returns null
以指示输入错误。