1

2013 年 6 月 1 日更新

我开发了一种扩展方法来解决这个特定问题,并且我在下面发布了该代码。我希望它可以帮助某人。

背景

我的任务是向应用程序添加功能,以允许设置定期会议(与 Outlook 完全相同)。

因此,例如,用户可能希望在每个月的第一个星期五、或每个月的最后一个星期一、或每个月的第二个工作日等召开会议。

是否存在用于此的标准算法?我找到了很多部分答案,但是没有什么可以允许像这样的干净扩展方法:

  /// <summary>
        /// Accepts a date object and finds the next date given an ordinality and type.
        /// </summary>
        /// <param name="ordinality">The ordinality (e.g. "first", "second", "last", etc.)</param>
        /// <param name="dayType">The day type (e.g. "weekday", "Monday", "day", etc)</param>
        /// <returns>A new date object</returns>
 public static DateTime GetNextDateOfType(this DateTime date, string ordinality, string dayType)
 {
 //do stuff
return newDate;
}

我一直在断断续续地做这件事,但我一直在想肯定已经有一些东西了。

到目前为止我所拥有的:

     public static DateTime GetNextDateOfType(this DateTime date, string ordinality, string dayType)
        {
            var dateTest = new DateTime(date.Year, date.Month, 1);
            var dateFound = false;
            var ordinal = 1;
            var targetOrdinal = ordinality.ToOrdinal();

            while (!dateFound)
            {
                //Test for type:
                switch (dayType)
                {
                    case "day":
                        if (dateTest >= date)
                        {
                            if (ordinality == "last" && dateTest == dateTest.GetLastDayOfMonth() || dateTest.Day == targetOrdinal)
                            {
                                dateFound = true;
                            }
                        }
                        break;
                    case "weekday":
                        if (dateTest >= date && dateTest.IsWeekDay())
                        {
                            if (targetOrdinal == ordinal)
                            {
                                dateFound = true;
                            }
                            ordinal++;
                        }
                        break;
                    case "weekend day":
                        if (dateTest >= date && !dateTest.IsWeekDay())
                        {
                            dateFound = true;
                        }
                        break;
                    default:
                        if (dateTest >= date && dateTest.DayOfWeek == HelperMethods.GetDayOfWeekFromString(dayType))
                        {
                            dateFound = true;
                        }
                        break;
                }
   
                dateTest = dateTest.AddDays(1);

            }

            return dateTest;
        }

   public static DateTime GetLastDayOfMonth(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
        }

        public static int ToOrdinal(this string ordinal)
        {
            var result = 0;
            switch (ordinal.ToLower())
            {
                case "first":
                    result = 1;
                    break;
                case "second":
                    result = 2;
                    break;
                case "third":
                    result = 3;
                    break;
                case "fourth":
                    result = 4;
                    break;
                case "fifth":
                    result = 5;
                    break;
                default:
                    result = -1;
                    break;
            }
            return result;
        }

        public static bool IsWeekDay(this DateTime date)
        {
            var weekdays = new List<DayOfWeek>
                {
                    DayOfWeek.Monday,
                    DayOfWeek.Tuesday,
                    DayOfWeek.Wednesday,
                    DayOfWeek.Thursday,
                    DayOfWeek.Friday
                };

            return weekdays.Contains(date.DayOfWeek);
        }

        public static List<DateTime> GetWeeks(this DateTime month, DayOfWeek startOfWeek)
        {
            var firstOfMonth = new DateTime(month.Year, month.Month, 1);
            var daysToAdd = ((Int32)startOfWeek - (Int32)month.DayOfWeek) % 7;
            var firstStartOfWeek = firstOfMonth.AddDays(daysToAdd);

            var current = firstStartOfWeek;
            var weeks = new List<DateTime>();
            while (current.Month == month.Month)
            {
                weeks.Add(current);
                current = current.AddDays(7);
            }

            return weeks;
        }

        public static int GetWeekOfMonth(this DateTime date)
        {
            var beginningOfMonth = new DateTime(date.Year, date.Month, 1);

            while (date.Date.AddDays(1).DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
                date = date.AddDays(1);

            return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + 1;
        }
4

1 回答 1

1

在为此苦苦挣扎了一段时间后,这是我想出的解决方案。它是一种扩展方法(下面还有其他引用的扩展方法)。这不是我最优雅的代码,但它有效。如果我在自己的环境中简化它,我稍后会更新代码。

获取最接近传入日期的一个月的第二个*Monday* 的简单用法示例:

var newDate= someDate.GetNextDateOfType("second", "Monday");

编码:

    public static DateTime GetNextDateOfType(this DateTime date, string ordinality, string dayType)
            {
                var targetOrdinal = ordinality.ToOrdinal();
                var dateTest = (targetOrdinal > -1) ? new DateTime(date.Year, date.Month, 1) : date.GetLastDayOfMonth();
                var dateFound = false;
                var ordinal = 1;
                var ordinalReset = false;

                if (targetOrdinal > -1) //All cases EXCEPT "last"
                {
                    while (!dateFound)
                    {
                        if (dateTest.Month > date.Month && !ordinalReset)
                        {
                            ordinal = 1;
                            ordinalReset = true;
                        }

                        //Test for type:
                        switch (dayType)
                        {
                            case "day":
                                if (dateTest >= date)
                                {
                                    if (dateTest.Day == targetOrdinal)
                                    {
                                        dateFound = true;
                                    }
                                }
                                break;
                            case "weekday":
                                if (dateTest >= date && dateTest.IsWeekDay())
                                {
                                    if (targetOrdinal == ordinal)
                                    {
                                        dateFound = true;
                                    }
                                }

                                if (dateTest.IsWeekDay())
                                {
                                    ordinal++;
                                }

                                break;
                            case "weekend day":
                                if (dateTest >= date && !dateTest.IsWeekDay())
                                {
                                    if (targetOrdinal == ordinal)
                                    {
                                        dateFound = true;
                                    }
                                }
                                if (!dateTest.IsWeekDay())
                                {
                                    ordinal++;
                                }

                                break;
                            default:
                                if (dateTest >= date && dateTest.DayOfWeek == HelperMethods.GetDayOfWeekFromString(dayType))
                                {
                                    if (targetOrdinal == ordinal)
                                    {
                                        dateFound = true;
                                    }
                                }

                                if (dateTest.DayOfWeek == HelperMethods.GetDayOfWeekFromString(dayType))
                                {
                                    ordinal++;
                                }
                                break;
                        }
                        dateTest = (dateFound) ? dateTest : dateTest.AddDays(1);
                    }
                }
                else //for "last"
                {
                    while (!dateFound)
                    {
                        if (dateTest <= date && !ordinalReset)
                        {
                            dateTest = date.GetLastDayOfMonth().AddMonths(1);
                            ordinalReset = true;
                        }

                        //Test for type:
                        switch (dayType)
                        {
                            case "day":
                                dateFound = true;
                                break;
                            case "weekday":
                                if (dateTest.IsWeekDay())
                                {
                                        dateFound = true;
                                }

                                break;
                            case "weekend day":
                                if (!dateTest.IsWeekDay())
                                {
                                    dateFound = true;
                                }
                                break;
                            default:
                                if (dateTest.DayOfWeek == HelperMethods.GetDayOfWeekFromString(dayType))
                                {
                                    dateFound = true;
                                }
                                break;
                        }
                        dateTest = (dateFound) ? dateTest : dateTest.AddDays(-1);
                    }
                }
                return dateTest;
            }

            public static DateTime GetLastDayOfMonth(this DateTime date)
            {
                return new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
            }

            public static int ToOrdinal(this string ordinal)
            {
                var result = 0;
                switch (ordinal.ToLower())
                {
                    case "first":
                        result = 1;
                        break;
                    case "second":
                        result = 2;
                        break;
                    case "third":
                        result = 3;
                        break;
                    case "fourth":
                        result = 4;
                        break;
                    case "fifth":
                        result = 5;
                        break;
                    default:
                        result = -1;
                        break;
                }
                return result;
            }

            public static bool IsWeekDay(this DateTime date)
            {
                var weekdays = new List<DayOfWeek>
                    {
                        DayOfWeek.Monday,
                        DayOfWeek.Tuesday,
                        DayOfWeek.Wednesday,
                        DayOfWeek.Thursday,
                        DayOfWeek.Friday
                    };

                return weekdays.Contains(date.DayOfWeek);
            }

            public static List<DateTime> GetWeeks(this DateTime month, DayOfWeek startOfWeek)
            {
                var firstOfMonth = new DateTime(month.Year, month.Month, 1);
                var daysToAdd = ((Int32)startOfWeek - (Int32)month.DayOfWeek) % 7;
                var firstStartOfWeek = firstOfMonth.AddDays(daysToAdd);

                var current = firstStartOfWeek;
                var weeks = new List<DateTime>();
                while (current.Month == month.Month)
                {
                    weeks.Add(current);
                    current = current.AddDays(7);
                }

                return weeks;
            }

            public static int GetWeekOfMonth(this DateTime date)
            {
                var beginningOfMonth = new DateTime(date.Year, date.Month, 1);

                while (date.Date.AddDays(1).DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
                    date = date.AddDays(1);

                return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + 1;
            }


 public static DayOfWeek GetDayOfWeekFromString(string day)
        {
            var dow = DayOfWeek.Sunday;
            switch (day)
            {
                case "Sunday":
                    dow = DayOfWeek.Sunday;
                    break;
                case "Monday":
                    dow = DayOfWeek.Monday;
                    break;
                case "Tuesday":
                    dow = DayOfWeek.Tuesday;
                    break;
                case "Wednesday":
                    dow = DayOfWeek.Wednesday;
                    break;
                case "Thursday":
                    dow = DayOfWeek.Thursday;
                    break;
                case "Friday":
                    dow = DayOfWeek.Friday;
                    break;
                case "Saturday":
                    dow = DayOfWeek.Saturday;
                    break;
            }

            return dow;
        }
于 2013-06-01T17:44:14.503 回答