/// <summary>
        /// Creates a relative date expression with symbol scope, context, script refernce set.
        /// The date expression can handle relative dates: 3rd monday of january
        /// </summary>
        /// <param name="name"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Expr DateRelative(string relativeDay, int dayOfWeek, int month, TokenData token)
        {
            var exp = new DateRelativeExpr();

            exp.RelativeDay  = relativeDay;
            exp.Month        = month;
            exp.DayOfTheWeek = dayOfWeek;
            SetupContext(exp, token);
            return(exp);
        }
 /// <summary>
 /// Visit the relative date expression.
 /// </summary>
 /// <param name="expr"></param>
 /// <returns></returns>
 public object VisitDateRelative(DateRelativeExpr expr)
 {
     return(null);
 }
        public object VisitDateRelative(DateRelativeExpr expr)
        {
            var year      = DateTime.Now.Year;
            var month     = expr.Month;
            var dayofWeek = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), expr.DayOfTheWeek.ToString());

            var date = new DateTime(year, month, 1);

            var DaysInWeek = 7;

            // move to holiday day of week
            var dayInc = 0;

            while (date.DayOfWeek != dayofWeek && dayInc <= DaysInWeek)
            {
                date = date.AddDays(1);
                dayInc++;
            }

            var relDay = expr.RelativeDay.ToLower();

            // Case 1: "last" <day> of <month>
            if (relDay == "last")
            {
                // 1. Add 2 weeks at least
                date = date.AddDays(14);

                var i = 0;
                var totalDaysInMonth = _daysInMonth[date.Month];
                while (i < 2)
                {
                    // 2. feb check
                    if (date.Month == 2 && (date.Day + 7) <= 28)
                    {
                        date = date.AddDays(7);
                    }
                    else if (date.Day + 7 <= totalDaysInMonth)
                    {
                        date = date.AddDays(7);
                    }
                    i++;
                }
            }
            // Case 2:
            else
            {
                var weekCount = 0;
                if (relDay == "first")
                {
                    weekCount = 1;
                }
                else if (relDay == "second")
                {
                    weekCount = 2;
                }
                else if (relDay == "third")
                {
                    weekCount = 3;
                }
                else if (relDay == "fourth")
                {
                    weekCount = 4;
                }

                // Case 2a: "first|second|third|fourth" of month
                if (weekCount > 0)
                {
                    date = date.AddDays((weekCount - 1) * DaysInWeek);
                }
                // Case 2b: ( 1st | 2nd | 3rd| 4th ) of month
                else
                {
                    weekCount = Convert.ToInt32(expr.RelativeDay);
                    date      = date.AddDays((weekCount - 1) * DaysInWeek);
                }
            }
            return(new LDate(date));
        }