如何确定c#中给定日期时间的第n天类型?

时间:2013-05-31 20:37:32

标签: c# datetime

更新日期6/1/2013

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

背景

我的任务是为应用添加功能,以便设置定期会议(与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;
        }

1 个答案:

答案 0 :(得分:1)

经过一段时间的努力,这是我提出的解决方案。它是一种扩展方法(在其下面有其他引用的扩展方法)。这不是我最优雅的代码,但它有效。如果我在自己的环境中简化代码,我将在稍后更新代码。

获取最接近传入日期的 second * 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;
        }