- 2006年以前
- 4月第1日曜日~10月最終日曜日
- 2007年以降
- 3月第2日曜日~11月第1日曜日
ある日がサマータイム期間に入っているかどうかを判定するためには、第n日曜日以降なのかどうかを調べる必要があります。
Java ならこうするだけなのですが、今回は MetaTrader での実現を考えました。MetaTrader ではサマータイム情報を持っていないため、算出してみようという話です。
課題設定
- 入力
- $Y$ (1970〜): 判定対象の年
- $M$ (1〜12): 判定対象の月
- $D$ (1〜31): 判定対象の日
- $n$ (1〜5): 基準を第$n$日曜日とする
- 出力
- 判定対象の日付が第$n$日曜日以降であれば$true$, 異なれば$false$
アルゴリズム
すぐに思い付く方法は、- $Y, M$ から月初日の曜日を算出する
- そこから、第$n$日曜日が何日かを算出する
- それと$D$を比較する
となるかと思います。
しかし、第$n$日曜日の日付を算出しなくても、もっと直接的に評価できます。
- $Y, M, D$から曜日 $W (日: 0, 月: 1, \cdots, 土: 6)$を算出する
- $D - W \ge 7(n-1)+1 $ ならば第$n$日曜日以降と判定
ちなみに Java での判定ロジックも追ってみましたが、同様の考え方になっていました。
バリエーション
最終日曜日なら、$ 7(n-1)+1 $の代わりに $月末日 - 7 + 1$ となります。月末日は求めないといけません。日曜日以外なら、$+1$ を $+2, +3, \cdots, +7$ とすれば良いでしょう。実装例 (MetaTrader4)
では、このロジックを使って、MetaTrader4 でサマータイム判定ロジックを組んでみます。
bool IsNewyorkSummerTimeSeason(datetime dt) { int y; switch (TimeMonth(dt)) { case 1: case 2: return(false); case 3: y = TimeYear(dt); if (y < 2007 || (y >= 2007 && TimeDay(dt) - TimeDayOfWeek(dt) < 8)) { return(false); } return(true); case 4: if (TimeYear(dt) < 2007 && TimeDay(dt) - TimeDayOfWeek(dt) < 1) { return(false); } case 5: case 6: case 7: case 8: case 9: return(true); case 10: y = TimeYear(dt); if (y >= 2007 || (y < 2007 && TimeDay(dt) - TimeDayOfWeek(dt) < 25)) { return(true); } return(false); case 11: if (TimeYear(dt) >= 2007 && TimeDay(dt) - TimeDayOfWeek(dt) < 1) { return(true); } case 12: return(false); } return(false); }
9、14、25、30行目で、今回のロジックを使っています。25行目は10月の最終日曜日判定です。10月末は31日と分かっているので、固定値で25と書けます。