| July 4 | The fourth of July. |
| oct 31 | Halloween |
| june 10-26 | June 10th through June 26th |
| August 27 - September 3 | The week spanning August and September |
| June - August | The summer months |
| last Thursday | The last Thursday of each month |
| fourth Thursday in November | Thanksgiving |
| first and third Wednesdays | The first and third Wednesdays of each month |
| last thurs jun-sep | The last Thursdays of June, July, August, and September |
| first and third Wednesdays except in June | The first and third Wednesdays of each month, except in June |
Any words that you type in are classified first as being a week ("first"-"fifth" or "last"), a weekday ("Sunday"-"Saturday"), a month ("January"-"December"), or a day of the month ("1" - "31"). A few other special words such as "through" and "except" are also detected. Most of these special words allow abbreviations and synonyms. Anything else is ignored.
The words are then grouped into clauses, where each clause consists of a list of zero or more weeks, then zero or more weekdays, then zero or more months, and finally zero or more days of the month. They must appear in that order; any deviation from that order marks the end of one clause and the start of another. For example, "June 7 Thursday" is divided into the clauses "June 7" and "Thursday".
The word "to" (or its synonyms, such as "-" and "through") is replaced by a list of the actual in the range. For example, in "first - third Mondays", the "-" is replaced by "second".
There's also some special logic for date ranges that span months, such as "August 27 - September 3". This logic is limited, though, in that it can't handle clauses that involve weeks or weekdays; for example, "last Thursday June 20 - September 21" doesn't work. (But "Last Thursday June-September" does work because "June-September" doesn't need the complex, limited logic.)
A given day is considered to "match" a clause if it doesn't violate any of the non-empty lists for week, weekday, month, or month-day. For example, if the clause is "first and third wednesdays" then a date will match if it is in the first or third week of the month, and it is a Wednesday. Since this particular clause didn't mention months or month-days, those won't play a role in the matching.
All of the clauses are merged together. A day is included in the event if it matches any of the clauses.
You can also have the word "except" (or "but") followed by more clauses. If you do this, then a day must also not be in any of the "except" clauses, to be included in the event.
Once the match rules and exception rules are established, the code loops through all days starting with today and extending forward either 365 days, or until a 180-day (or longer) gap is detected between days, whichever comes first. Each day is tested against the match/exception rules, and if it looks good then it is added to the matching list.
The gap rule is added because if you say something occurs in July, and the current month is July, then you probably don't mean one week now and three weeks a year from now.