Although I am not ready to release msdk module for Magento, I finish a model called Qian_Msdk_Model_Nwd. It is to judge if a given date is a non working day by some pre-defined and user-defined rules. It can also work out what date of next n’th working day is.
There are two types of rules, rule by date or rule by week. For Non Working Day (NWD) fixed by date, there is normally a make-up following working day as NWD if the original one is Saturday or Sunday. For NWD fixed by week, there is no make-up, usually.
For the rule simplicity, I always assume make-up. When you are writing your own rules and do not want make-up to some rules, add “=” modifier to the beginning of each of them.
How to read and write NWD rules?
First thing to remember, as a general checking rule, I go through each line separated by “\n”, and verify if the supplied date (if omitted, assume today’s date) fall into the line of rule. There is no connection between lines, so do not expect a rule can make up another one.
Second thing to remember, as PHP allows a date like “2010/13/33”, I allow you write rules like that too. However, avoid it if you can.
Third thing to remember, PHP regards Sunday as 0 Saturday as 6, and I do the same.
Fourth thing to remember, when ISO number weeks, it regards week starts Monday, and I do the same. If you do not know what I am talking about, read ISO-8601.
Fifth thing to remember, I do not have a good algorithm to work out dates by lunar calendar. So that is no smart way to write a rule for Easter. Ditto many Chinese holidays. You have to use fixed date every year. I hope it won’t cost you long time write down all fixed dates of 10 years lunar NWD and just sit while this programme runs for 10 years. After 10 years, aha, you’ll find your way.
OK, let’s get on to rule writing.
1. Rule by date is something like “yyyy/mm/dd”, or “yyyy/mm/dd,dd,dd”. yyyy, mm or dd can take asterisk “*” as wild-card.
For new year day, it is “*/01/01”. This is simplest scenario. For Christmas and Boxing day, it is “*/12/25,26”. Be careful here, do not write two rules “*/12/25” and “*/12/26”. They can not achieve the same result as “*/12/25,26”, because a rule can make up a following working day if the rule date is Saturday or Sunday, but it can not exclude days by other rules.
You have to write in one rule if two or more NWDs are connected. However, the dates are not necessarily continuous. In theory, you can write a rule like “*/12/24,26”. In reality, I did not see any NWDs are scheduled like this.
2. Rule by week is something like “yyyy/mm/dd/weekNumber/weekDay”, or “yyyy///weekNumber/weekDay”. yyyy, mm or dd can take asterisk “*” as wild-card. “yyyy///weekNumber/weekDay” use ISO-8601 to find the week and weekDay. I will cover it in section 3.
“yyyy/mm/dd/weekNumber/weekDay” uses a reference year/month/day to find the n’th weekDay. N is specified by weekNumber.
2.1 If both mm and dd are “*”, it uses a reference year. For example, “*/*/*/10/1” means 10th Monday of any year.
2.2 If mm is a number, but dd is “*”, it uses a reference month. For example, “*/05/*/1/1” means 1st Monday in May. A lot of England bank holidays are specified this way.
2.3 If dd is a number, it uses a reference day. For example, “*/06/06/0/1” means the Monday of the week where June 6 sits.
In case of 2.1 and 2.2, weekNumber can take a negative number which means the last n’th weekDay. For example, “*/05/*/-1/1” means the last Monday in May. WeekNumber zero does not make sense here.
In case of 2.3, weekNumber can take zero (means the same week), a positive number (n’th week forward), or a negative number (n’th week backward).
3. “yyyy///weekNumber/weekDay” ISO-8601 style looks similar to case 2.1. But they are totally different.
For example, “2011///1/6” means Saturday of week 1 of year 2011, which is 2011/01/08. But “2011/*/*/1/6” means the 1st Saturday of year 2011, which is 2011/01/01.
Another example, “2010///52/6” means Saturday of week 52 of year 2010, which is 2011/01/01 (Yes, it goes into the following year). But “2010/*/*/52/6” means the 52th Saturday of year 2010, which is 2010/12/25.
I think writing documentation helps programming. I have revised NWD documentation for 3 times or more, and every time I found a new way to structure the model.
I also think any date calculation look simple but actual coding is very complex. This model took me half a year to finish although I am full time on it.