我正在创建一个调度程序,并且需要能够在 C# 中执行以下操作:
- 查找 2012 年 6 月的第一个星期二
- 查找 2008 年 3 月的最后一个星期五
- 查找 2013 年 1 月的每个星期六
- 查找 2009 年 7 月的第三个星期五
- 查找未来 3 个月内的每个星期六
- 查找 2018 年 3 月的每一天
结果应该以DateTime
或的形式返回List<DateTime>
。
以下是查找给定月份中第一个/最后一个指定星期几的方法:
public DateTime GetFirstDayOfWeekInMonth(int year, int month, DayOfWeek dayOfWeek)
{
DateTime dt = new DateTime(year, month, 1);
int first = (int)dt.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted < first)
wanted += 7;
return dt.AddDays(wanted - first);
}
public DateTime GetLastDayOfWeekInMonth(int year, int month, DayOfWeek dayOfWeek)
{
int daysInMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(year, month);
DateTime dt = new DateTime(year, month, daysInMonth);
int last = (int)dt.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted > last)
last += 7;
return dt.AddDays(wanted - last);
}
从中,您可以轻松找到其他问题的答案......只需添加 7 天即可找到您正在寻找的下一个日期
编辑:多考虑一下,以扩展方法的形式使用它会非常方便,例如:
Console.WriteLine("Next monday : {0}", DateTime.Today.Next(DayOfWeek.Monday));
Console.WriteLine("Last saturday : {0}", DateTime.Today.Previous(DayOfWeek.Saturday));
这是实现:
public static class DateExtensions
{
public static DateTime Next(this DateTime from, DayOfWeek dayOfWeek)
{
int start = (int)from.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted < start)
wanted += 7;
return from.AddDays(wanted - start);
}
public static DateTime Previous(this DateTime from, DayOfWeek dayOfWeek)
{
int end = (int)from.DayOfWeek;
int wanted = (int)dayOfWeek;
if (wanted > end)
end += 7;
return from.AddDays(wanted - end);
}
}
它可能比我建议的第一种方法更灵活......有了它,你可以轻松地做这样的事情:
// Print all Sundays between 2009/01/01 and 2009/03/31
DateTime from = new DateTime(2009, 1, 1);
DateTime to = new DateTime(2009, 3, 31);
DateTime sunday = from.Next(DayOfWeek.Sunday);
while(sunday <= to)
{
Console.WriteLine(sunday);
sunday = sunday.AddDays(7);
}
受这个问题的启发,制作一些允许您将日期视为序列并使用 LINQ 查询它们的东西似乎是一件有趣的事情。我做了一个简单的项目,可以从 GitHub下载。不知道是否有必要将其添加到源代码管理中,因为我怀疑我是否会处理它,但必须将其上传到某个地方并将其上传到 RapidShare 似乎有点狡猾:)
我的“Linq-to-DateTime”解决了您的第一个问题:
/*
* 1. Find the 1st Tuesday of June 2012
2. Find the last Friday of March 2008
3. Find every Saturday in January 2013
4. Find the 3rd Friday in July 2009
5. Find every Saturday over the next 3 months
6. Find every day in March 2018
*/
var firstTuesday = (from d in DateSequence.FromYear(2012).June()
where d.DayOfWeek == DayOfWeek.Tuesday
select d).First();
var lastFriday = (from d in DateSequence.FromYear(2008).March()
where d.DayOfWeek == DayOfWeek.Friday
select d).Last();
var saturdays = (from d in DateSequence.FromYear(2013).January()
where d.DayOfWeek == DayOfWeek.Saturday
select d);
var thirdFriday = (from d in DateSequence.FromYear(2009).July()
where d.DayOfWeek == DayOfWeek.Friday
select d).Skip(2).First();
var nextSaturdays = (from d in DateSequence.FromDates(DateTime.Today, DateTime.Today.AddMonths(3))
where d.DayOfWeek == DayOfWeek.Saturday
select d);
var allDays = (from d in DateSequence.FromYear(2018).March()
select d);
此示例中未显示的是您可以选择查询的粒度。这意味着如果你这样做:
var days = (from d in DateSequence.FromYears(2001, 2090).AsYears()
where d.Year % 2 == 0
select d.Year).ToList();
您将以一年为增量迭代日期。如果您未指定任何内容,则默认值为 AsDays()。
该项目非常简单,没有评论或单元测试,但我希望这仍然可以帮助你。如果没有,那么无论如何写作都很有趣:)
这是一个关于如何做一个月的第一天的例子。
public enum Month
{
January = 1,
Febuary = 2,
March = 3,
April = 4,
May = 5,
June = 6,
July = 7,
August = 8,
September = 9,
October = 10,
November = 11,
December = 12
}
public static Nullable<DateTime> FindTheFirstDayOfAMonth(DayOfWeek dayOfWeek, Month month, int year)
{
// Do checking of parameters here, i.e. year being in future not past
// Create a DateTime object the first day of that month
DateTime currentDate = new DateTime(year, (int)month, 1);
while (currentDate.Month == (int)month)
{
if (currentDate.DayOfWeek == dayOfWeek)
{
return currentDate;
}
currentDate = currentDate.AddDays(1);
}
return null;
}
你这样称呼它
Nullable<DateTime> date = Program.FindTheFirstDayOfAMonth(DayOfWeek.Monday, Month.September, 2009);
所以你明白了。您将必须执行各种功能才能获得您想要实现的目标。
YO YO YO - 你们太难了:
int DaysinMonth = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
当我编写调度程序时,我几乎复制了 SQL Servers sysschedules 表
http://msdn.microsoft.com/en-us/library/ms178644.aspx
使用频率类型、频率间隔等……确实可以很容易地计算代码中的值,但我猜有一个 sproc 可以为你做这件事。我现在正在寻找那个。
是的,他们.NET Framework
会毫无问题地支持它;)
但说真的 - 你应该能够编写相当容易做到这一点的代码。如果没有,请在遇到困难时提出问题,我们会提供帮助。但是您不需要任何外部程序集 - 只需使用标准 C# 类 =)