确定一个月的第一天、一个月的最后一天等的函数。

发布于 2024-08-06 07:35:51 字数 317 浏览 4 评论 0原文

我正在创建一个调度程序,需要能够在 C# 中执行以下操作:

  1. 查找 2012 年 6 月的第一个星期二
  2. 查找 2008 年 3 月的最后一个
  3. 星期五 查找 2013 年 1 月的每个星期六
  4. 查找 2009 年 7 月的第 3 个星期五
  5. 查找 2009 年 7 月的每个星期六接下来 3 个月
  6. 查找 2018 年 3 月的每一天

结果应以 DateTimeList 形式返回。

I'm creating a scheduler and need to be able to do the following in C#:

  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

The results should come back as DateTime or List<DateTime>.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

早乙女 2024-08-13 07:35:51

以下是查找给定月份中一周的第一天/最后一天的方法:

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

Here are methods to find the first/last specified day of week in a given month:

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

From those, you can easily find the answers to the other questions... just add 7 days to find the next occurence of the day you're looking for


EDIT: thinking more about it, it would be pretty handy to have that in the form of extension methods, such as :

Console.WriteLine("Next monday : {0}", DateTime.Today.Next(DayOfWeek.Monday));
Console.WriteLine("Last saturday : {0}", DateTime.Today.Previous(DayOfWeek.Saturday));

Here is the implementation :

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

It's probably more flexible than the first methods I suggested... With that, you can easily do things like that :

// 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);
}
灵芸 2024-08-13 07:35:51

受这个问题的启发,制作一些东西来允许您将日期视为序列并使用 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()。

该项目非常简单,没有评论或单元测试,但我希望这仍然可以帮助您。如果没有,那么无论如何,写起来很有趣:)

Inspired by this question it seemed like a fun thing to make something that allows you to treat dates as sequences and query them with LINQ. I've made a simple project that can be downloaded here from GitHub. Don't know if it was necessary to add it to source control as I doubt I'll be working on it, but had to upload it somewhere and uploading it to RapidShare seemed a little dodgy :)

Your first questions solved with my "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);

Not shown in this example is that you can choose the granularity of your queries. Meaning that if you do this:

  var days = (from d in DateSequence.FromYears(2001, 2090).AsYears()
              where d.Year % 2 == 0
              select d.Year).ToList();

You will iterate through the dates with an increment of a year. The default is AsDays() if you don't specify anything.

The project is pretty barebone, no commentary or unit tests, but I hope this can still help you. If not, then it was fun writing anyway :)

机场等船 2024-08-13 07:35:51

以下是如何处理每月第一天的示例。

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

所以你明白了。您将必须执行各种功能才能获得您想要实现的目标。

Here is an example on how to do the first day of a month.

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

You call it like

Nullable<DateTime> date = Program.FindTheFirstDayOfAMonth(DayOfWeek.Monday, Month.September, 2009);

So you get the idea. You will have to do various functions do get what you want to achieve.

吾家有女初长成 2024-08-13 07:35:51

YO YO YO - 你们把这件事搞得太难了:

int DaysinMonth = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);

YO YO YO - You guys are making this too hard:

int DaysinMonth = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);

楠木可依 2024-08-13 07:35:51

当我编写调度程序时,我几乎复制了 SQL Server sysschedules 表

http://msdn .microsoft.com/en-us/library/ms178644.aspx

使用诸如频率类型、频率间隔等之类的东西...确实可以轻松计算代码中的值,但我猜测有一个存储过程为你做这件事。我现在正在寻找那个。

When I wrote a scheduler I pretty much copied SQL Servers sysschedules table

http://msdn.microsoft.com/en-us/library/ms178644.aspx

Using things like Frequency Type, Frequency Interval, etc... really made it easy to compute the values in code, but I am guessing there is a sproc to do it for you. I am searching for that now.

挽容 2024-08-13 07:35:51

是的,.NET Framework 将支持这一点,不会出现任何问题;)

但认真地说,您应该能够编写相当容易实现这一点的代码。如果没有,请在遇到困难时提出问题,我们会提供帮助。但您不需要任何外部程序集 - 只需使用标准 C# 类 =)

Yes, the .NET Framework will support that without any problems ;)

But seriously - you should be able to write code that does that fairly easily. If not, ask a question when you get stuck, and we'll help out. But you won't need any external assemblies - just go with a standard C# class =)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文