如何确定日期是否是第 n 个列表一个月内?

发布于 2024-12-04 04:43:18 字数 369 浏览 1 评论 0原文

我见过 这个问题,它查找特定月份中的第 N 个工作日,但我想要一些可以查找给定月份中第 N 个[工作日列表] 的内容。有没有一种简单的方法可以做到这一点,而无需循环遍历该月的每一天?

例如,如果我说我想要一个月中的第 3 个 [周一、周三、周五],并且该月从周三开始,则它应该返回第一个周一(1 = 周三,2 = 周五) , 3 = 星期一)。如果我说我想要倒数第二个[周一、周二、周三、周四],并且该月的最后一天是周日,那么它应该返回上一个周三。

I've seen this question, which looks for the Nth weekday in a specific month, but I want something that will look for the Nth [weekday list] in a given month. Is there an easy way to get that without looping through every day in the month?

For example, if I say I want the 3rd [Mon, Wed, Fri] in a month, and the month starts on a Wednesday, it should return the 1st Monday (1 = Wed, 2 = Fri, 3 = Mon). If I say I want the 2nd last [Mon, Tue, Wed, Thurs] and the last day of the month is a Sunday, it should return the previous Wednesday.

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

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

发布评论

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

评论(2

不及他 2024-12-11 04:43:18

嗯,我的意思是,你也许能够想出一些丑陋且难以理解的东西,它是基于公式的,并且避免循环,但它会丑陋且难以理解,容易出现错误,而且会造成维护灾难,而且尝试起来一点也不有趣。和。

相反,只需想出使用循环可以轻松编写的内容,然后使用 LINQ隐藏 循环即可:

static class DateTimeExtensions {
    private static IEnumerable<DateTime> DaysOfMonth(int year, int month) {
        return Enumerable.Range(1, DateTime.DaysInMonth(year, month))
                         .Select(day => new DateTime(year, month, day));
    }

    public static DateTime NthDayOfMonthFrom(
        this HashSet<DayOfWeek> daysOfWeek,
        int year,
        int month,
        int nth
    ) {
        return
            DateTimeExtensions.DaysOfMonth(year, month)
                              .Where(
                                   date => daysOfWeek.Contains(date.DayOfWeek)
                              )
                              .Skip(nth - 1)
                              .First();
    }
}

用法:

var daysOfWeek = new HashSet<DayOfWeek> {
    DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday
};
DateTime date = daysOfWeek.NthDayOfMonthFrom(2011, 6, 3));
Assert.Equal(date, new DateTime(2011, 6, 6));

同样,使用 Reverse,您可以轻松编写 NthLastDayOfWeekFrom。我会让你想出一个更好的名字。

Meh I mean you might be able to come up with something ugly and incomprehensible that is formula-based and avoids looping, but it will be ugly and incomprehensible so bug-prone and a maintenance disaster, and not at all fun to try to come up with.

Instead, just come up with what is easy to write using loops, and then hide the loops by using LINQ:

static class DateTimeExtensions {
    private static IEnumerable<DateTime> DaysOfMonth(int year, int month) {
        return Enumerable.Range(1, DateTime.DaysInMonth(year, month))
                         .Select(day => new DateTime(year, month, day));
    }

    public static DateTime NthDayOfMonthFrom(
        this HashSet<DayOfWeek> daysOfWeek,
        int year,
        int month,
        int nth
    ) {
        return
            DateTimeExtensions.DaysOfMonth(year, month)
                              .Where(
                                   date => daysOfWeek.Contains(date.DayOfWeek)
                              )
                              .Skip(nth - 1)
                              .First();
    }
}

Usage:

var daysOfWeek = new HashSet<DayOfWeek> {
    DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday
};
DateTime date = daysOfWeek.NthDayOfMonthFrom(2011, 6, 3));
Assert.Equal(date, new DateTime(2011, 6, 6));

Similarly, using Reverse, you can easily write NthLastDayOfWeekFrom. I'll leave it to you to come up with a better name.

筱武穆 2024-12-11 04:43:18

我想我接受杰森的回答,因为我喜欢他的解决方案,但是这是我在看到他的帖子之前想到的。我想我会发布它,因为我喜欢不彻底循环每个日期的想法,特别是如果 N 是一个更高的值并且我想获得当前月份之外的日期。

我没有循环遍历所有日期,而是快进(如果要倒退,则快退)到最近的一周,然后循环遍历接下来的几天以查找工作日指定的第 N 个实例。

public static DateTime? GetNthWeekDayInMonth(DateTime month, int nth, List<DayOfWeek> weekdays)
{
    var multiplier = (nth < 0 ? -1 : 1);
    var day = new DateTime(month.Year, month.Month, 1);

    // If we're looking backwards, start at end of month
    if (multiplier == -1) day = day.AddMonths(1).AddDays(-1);

    var dayCount = weekdays.Count;

    if (dayCount == 0)
        return null;

    // Fast forward (or rewind) a few days to appropriate week
    var weeks = ((nth - (1 * multiplier)) / dayCount);
    day = day.AddDays(weeks * 7);

    // Current Nth value
    var currentNth = (1 * multiplier) + (weeks * dayCount);

    // Loop through next week looking for Nth value
    for (var x = 0; x <= 7; x++)
    {
        if (weekdays.Contains(day.DayOfWeek))
        {
            if (currentNth == nth)
            {
                // Verify the nth instance is still in the current month
                if (day.Month == month.Month)
                    return day;
                else
                    return null;
            }

            currentNth += multiplier;
        }

        day = day.AddDays(multiplier);
    }

    return null;

}

I think I'm accepting Jason's answer because I like his solution, however here's what I had come up with before I saw his post. I thought I'd post it because I like the idea of not looping thorough every date, especially if N is a higher value and I'd like to get a date outside the current month.

Instead of looping through all days, I fast-forwarded (or rewind if I'm going backwards) to the closest week, then looped through the next couple of days to find the Nth instance the weekdays specified.

public static DateTime? GetNthWeekDayInMonth(DateTime month, int nth, List<DayOfWeek> weekdays)
{
    var multiplier = (nth < 0 ? -1 : 1);
    var day = new DateTime(month.Year, month.Month, 1);

    // If we're looking backwards, start at end of month
    if (multiplier == -1) day = day.AddMonths(1).AddDays(-1);

    var dayCount = weekdays.Count;

    if (dayCount == 0)
        return null;

    // Fast forward (or rewind) a few days to appropriate week
    var weeks = ((nth - (1 * multiplier)) / dayCount);
    day = day.AddDays(weeks * 7);

    // Current Nth value
    var currentNth = (1 * multiplier) + (weeks * dayCount);

    // Loop through next week looking for Nth value
    for (var x = 0; x <= 7; x++)
    {
        if (weekdays.Contains(day.DayOfWeek))
        {
            if (currentNth == nth)
            {
                // Verify the nth instance is still in the current month
                if (day.Month == month.Month)
                    return day;
                else
                    return null;
            }

            currentNth += multiplier;
        }

        day = day.AddDays(multiplier);
    }

    return null;

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