代码改变世界

計算某天屬於當月的第幾週的簡單方法(最終版)

2010-08-11 17:35  Koy  阅读(472)  评论(0编辑  收藏  举报

using System;

using System.Collections.Generic;

using System.Text;


namespace PMSLib.Utils {

    public sealed class SpecialDateTime {

        private int _year, _month, _day;

        private int _week;

        private int _maxDays;


        public SpecialDateTime(int year, int month, int day) {

            _year = year;

            _month = month;

            _day = day;


            _maxDays = DateTime.DaysInMonth(year, month);

        }

        public SpecialDateTime(int year, int month) {

            _year = year;

            _month = month;

            _day = 1;


            _maxDays = DateTime.DaysInMonth(year, month);

        }

        public SpecialDateTime() { }


        public int Removal {

            get {

                int removal = 7 - (int)(new DateTime(_year, _month, 1).DayOfWeek);

                return removal == 7 ? 0 : removal;

            }

        }

        public int Markup {

            get {

                return (6 - (int)(new DateTime(_year, _month, _maxDays).DayOfWeek));

            }

        }


        public int WeeksInMonth {

            get {

                return (_maxDays + Markup - Removal) / 7;

            }

        }

        public int DaysInMonth {

            get { return (EndDateOfMonth - StartDateOfMonth).Days + 1; }

        }

        public DateTime StartDateOfMonth {

            get { return new DateTime(_year, _month, 1).AddDays(Removal); }

        }

        public DateTime EndDateOfMonth {

            get { return new DateTime(_year, _month, _maxDays).AddDays(Markup); }

        }


        public void GetWeekInMonthBy(int year, int month, int day, out int realMonth, out int week) {

            int removal = 7 - (int)(new DateTime(year, month, 1).DayOfWeek);

            removal = removal == 7 ? 0 : removal;


            TimeSpan ts = new DateTime(year, month, day) - new DateTime(year, month, 1).AddDays(removal);

            if(ts.Days < 0) {

                realMonth = month - 1;

                removal = 7 - (int)(new DateTime(year, realMonth, 1).DayOfWeek);

                removal = removal == 7 ? 0 : removal;


                TimeSpan ts1 = new DateTime(year, month, day) - new DateTime(year, realMonth, 1).AddDays(removal);

                week = (int)Math.Ceiling(ts1.Days == 0 ? 1 : (ts1.Days) * 1.0 / 7);

            } else {

                realMonth = month;

                week = (int)Math.Ceiling(ts.Days == 0 ? 1 : ts.Days * 1.0 / 7);


                if(ts.Days != 0 && ts.Days % 7 == 0) {

                    week = week + 1;

                }

            }

        }

        public DateTime GetDateBy(int year, int month, int weekInMonth, DayOfWeek dayOfWeek) {

            if(month > 12) {

                year += month / 12;

                month = month % 12;

            }

            int removal = 7 - (int)(new DateTime(year, month, 1).DayOfWeek);

            removal = removal == 7 ? 0 : removal;


            DateTime startDate = new DateTime(year, month, 1).AddDays(removal);

            return startDate.AddDays((weekInMonth - 1) * 7 + (int)dayOfWeek);

        }

        public void GetDateRangeInWeek(int year, int month, int week, out DateTime startDate, out DateTime endDate) {

            startDate = (new DateTime(year, month, 1).AddDays(Removal).AddDays((week - 1) * 7));

            endDate = (new DateTime(year, month, 1).AddDays(Removal).AddDays((week - 1) * 7 + 6));

        }


        public IList<DateTime> GetDatesBy(int minWeekInMonth, DayOfWeek dow, int interval) {

            IList<DateTime> dates = new List<DateTime>();


            while(GetDateBy(_year, _month, minWeekInMonth, dow) <= EndDateOfMonth) {

                dates.Add(GetDateBy(_year, _month, minWeekInMonth, dow));

                minWeekInMonth += interval;

            }


            return dates;

        }


        public IList<DateTime> GetDatesBy(DateTime date, int interval, string unit, int realMonth) {

            IList<DateTime> dates = new List<DateTime>();


            SpecialDateTime sdt = new SpecialDateTime(date.Year, realMonth);

            if(unit.Equals("W")) {

                do {

                    DateTime d = date.AddDays(7 * interval);

                    if(sdt.StartDateOfMonth > d || d > sdt.EndDateOfMonth) break;


                    dates.Add(d);

                    date = d;

                } while(sdt.StartDateOfMonth <= date && date <= sdt.EndDateOfMonth);

            } else {

                int week, month;

                sdt.GetWeekInMonthBy(date.Year, date.Month, date.Day, out month, out week);


                DateTime d = sdt.GetDateBy(date.Year, month + interval, week, date.DayOfWeek);

                if(realMonth == month + interval) {

                    dates.Add(d);

                }

            }


            return dates;

        }

    }

}