如何让我的IsItAHoliday功能更高效?

时间:2014-03-17 04:52:13

标签: c# function datetime performance

如果是周末或其中一个假期,我有一个应该返回1的方法:元旦,阵亡将士纪念日,独立日,劳动节,感恩节&圣诞节,否则为0。我已经选择使用DateTime.DayOfYear和DateTime.IsLeapYear的组合来实现代码,但我觉得这样效率非常低,并且使得像阵亡将士纪念日(5月的最后一个星期一!)这样的假期变得更加困难。如何有效地实现我的目标,并且不用硬编码每年更改日期的假期?

这是我目前的实施:

    private int IsItAHoliday(DateTime time)
    {
        // Assume it is not a weekend
        int isWeekendOrHoliday = 0;

        // TODO: Memorial Day, Labor Day, Thanksgiving
        // Declare holidays
        int christmasDayNonLeapYearIndex = 359;
        int christmasDayLeapYearIndex = 360;
        int newYearsDayIndex = 1;
        int independenceDayNonLeapYearIndex = 185;
        int independenceDayLeapYearIndex = 186;

        // Find out if time falls on a weekend
        if (time.DayOfWeek == DayOfWeek.Saturday || time.DayOfWeek == DayOfWeek.Sunday)
        {
            isWeekendOrHoliday = 1;
        }
        // Find out if time falls on a holiday
        // Leap year
        if (DateTime.IsLeapYear(time.Year))
        {
            if ((time.DayOfYear == christmasDayLeapYearIndex) || (time.DayOfYear == independenceDayLeapYearIndex) || (time.DayOfYear == newYearsDayIndex))
            {
                isWeekendOrHoliday = 1;
            }
        }
        // Non-leap year
        else if (!DateTime.IsLeapYear(time.Year))
        {
            if ((time.DayOfYear == christmasDayNonLeapYearIndex) || (time.DayOfYear == independenceDayNonLeapYearIndex) || (time.DayOfYear == newYearsDayIndex))
            {
                isWeekendOrHoliday = 1;
            }
        }

        return isWeekendOrHoliday;
    }

3 个答案:

答案 0 :(得分:3)

常用方法是定义描述假日日期的一组规则:

public interface IHoliday
{
  bool isHoliday(DateTime date);
}

然后为不同的假日模式实现接口。例如,确切的日期假期:

public class ExactDayHoliday : IHoliday
{
  public int Day {get; set;}
  public int Month {get; set;}

  public bool isHoliday(DateTime date)
  {
    return date.Month == month && date.Day == day;
  }
}

另一个规则的例子:一个月的第n周。

public class DayOfWeekHoliday : IHoliday
{
    public int Nth { get; set; }
    public DayOfWeek DayOfWeek { get; set; }
    public int Month { get; set; }

    public bool isHoliday(DateTime date)
    {
        return date.Month == Month && date.DayOfWeek == DayOfWeek && (date.Day - 1) / 7 == (Nth - 1);
    }
} 

创建所有假期的规则列表。例如:

List<IHoliday> holidays = new List<IHoliday> {new ExactDayHoliday {Month = 12, Day = 25}, new DayOfWeekHoliday {Nth = 1, DayOfWeek = DayOfWeek.Monday, Month = 9}};

最后一步(检查指定日期):

bool isHoliday = holidays.Any(rule => rule.IsHoliday(date));

答案 1 :(得分:0)

如果您要对应用程序支持的每个事件进行硬编码,我建议您使用Enumerations:

    public enum Holidays{
    newYearsDayIndex = 1,
    independenceDayNonLeapYearIndex = 185,
        independenceDayLeapYearIndex = 186,
    christmasDayNonLeapYearIndex = 359,
        christmasDayLeapYearIndex = 360
    }

然后使用每个的值作为假日的日期索引和名称来解释为什么这一天是假日

    Enum.GetValues(typeof(Holidays)); --> For values which you will use as days Index
    Enum.GetNames(typeof(Holidays)); --> For Names which you will use to describe the picked date

您也可以考虑将单独的枚举中的闰假和非闰假与您的命名约定分开

答案 2 :(得分:0)

你不需要在假期检查YEAR,因为它们每年都出现在相同的日期,例如12月25日,1月1日等。

我很快编译了一些代码:

public class Holiday
{
    public int Day {get; private set;}
    public int Month {get; private set;}
    public Holiday(int day, int month)
    {
        this.Day = day;
        this.Month = month;
    }

    public bool IsEqual(DateTime dateTime)
    {
        return ((this.Day == dateTime.Day) && (this.Month == dateTime.Month));
    }
}

public static class DateTimeExtensions
{
    private static List<Holiday> holidays = new List<Holiday>();

    public static void RegisterHoliday(Holiday holiday)
    {
        holidays.Add(holiday);
    }

    public static bool IsHoliday(this DateTime dateTime)
    {
        foreach (Holiday holiday in holidays)
        {
            if (holiday.IsEqual(dateTime)) return true;
        }
        return false;
    }

    public static bool IsWeekend(this DateTime dateTime)
    {
        return (dateTime.DayOfWeek == DayOfWeek.Sunday) || (dateTime.DayOfWeek == DayOfWeek.Saturday);
    }
}

现在使用Register方法添加假期并使用扩展程序。    DateTimeExtensions.RegisterHoliday(new Holiday(25, 12));

DateTime dateTimeToCheck = new DateTime(2013, 12, 25);    return dateTimeToCheck.IsHoliday() || dateTimeToCheck.IsWeekend();