14.3.曜日を求める | |||||||||
曜日計算は、いろいろな局面で必要となります。バックアップや、マーケティング分析や、あるいはシステムプログラムの制御など。 さて、やろうとしていることは、 あるサブルーチン(内部でも外部でも)に日付を渡すと、曜日コードが帰ってくればいいのです。大きく分けて、方法は3つあります。
曜日計算の方法
Zellerの公式
間違われている方もいらっしゃるようなので、以下に気をつけてください。 1月、2月は、前年の13月、14月として計算しますので、たとえば
として計算します。 オリジナル
お詫び[2000-3-1]
|
注意:この計算式はRPG、CLPに適しません。下記の変形をご利用下さい。掲示板で、指摘され、考えてみたら、整数の丸目の際、マイナスが有る場合に関して、はっきりと明確な答えが出ませんでした。-8.9を最も近い整数にまとめると言う場合、-9.0になる場合、-8.0になる場合、と2つ考えられます。実は、式の中にガウス記号[]があったので、気にとめていなかったのですが、RPGには、ガウス記号とか、「床」、「天井」の考え方がありませんでした。 小数以下を持つ数字を、整数にする場合、「床」(floor;xを越えない最大の整数)と「天井」(ceiling;xより小さくない最小の整数)があります。 floor(2.718)=2, floor(-2.718)=-3
ceil(2.718)=3, ceil(-2.718)=-2
RPGで「切り捨てる」場合、2.718=2となり、-2.718=-2になるので、正の整数では、floorで、負の整数では、ceilになります。そもそも切り捨てって、そういう物でしたね。(頭がごちゃごちゃしてきた...) 上記のEXCELシートでは、MOD(n,d) = n - d*INT(n/d)と考えていて、そのINT関数は、
となっているので、floorを使っています。つまりMOD(-23,7)は、EXCELと、MVRを使ったRPGでは異なる結果になります。 EXCELでは、MOD(-23,7)は、-23-(7*int(-23/7))=-23-(7*-4)=-23+28=5です。 RPGでは、DIVとMVRで、 -23 DIV 7 CHK1MVR CHK2 から、CHK1は-3で、CHK2は-2です。つまり、-23-(7*-3)=-23+21=-2になります。切り捨てをベースにしているからですね。
これでは、RPG(多分CLPも)で、簡単に値を求めるのは、無理でした。(2000年いっぱい)負数が出てしまうこの式よりも、この後で紹介する計算式の方がいいと思います。申し訳有りません。この方式での計算は止めてください。 これは、アルゴリズムだけでなく、それをRPGで如何に考えるのかまできちんと、フォローすべきでした。また、指摘していただきありがとうございました。 またこちらも、参考になります:FORTRAN CS1005: Homework 3 Finding Weekdays Given The Date負数なら+7でもいいようですね。[2000-3-8] [2000-3-1] |
計算結果が 0=日曜, 1=月曜, 2=火曜, 3=水曜、4=木曜, 5=金曜, 6=土曜となります。有効範囲は1583年から3999年まで。 ※上のオリジナルとは、曜日に対応する数字が違います。
| yyyy年mm月dd日の曜日は、(1月,2月は前年の13月,14月とみなす。)
( yyyy + [ yyyy / 4 ] - [ yyyy / 100 ] + [ yyyy / 400 ] + [ ( 2.6 * mm ) + 1.6 ] + dd ) mod 7 |
例 1997年11月24日
( 1997 + ( 1997 / 4 ) - ( 1997 / 100 ) + ( 1997 / 400 ) + [ ( 2.6 * 11 ) + 1.6 ] + 24 ) mod 7
= (1997+499-19+4+30+24) mod 7
= 2535 mod 7
= 1
= MondayEXCELで確認してみましょう。
2000-3-1
![]()
A1 B1 C1 D1 yyyy mm dd =MOD(A1+INT(A1/4)-INT(A1/100)+INT(A1/400)+INT((2.6*B1)+1.6)+C1,7)
基本原理はそれほど難しくありません。知っていると、ちょっとした話題作りになるかも。
つまり、今年と来年が平年であれば、今日の曜日は、来年は1曜日ずれます。今日が月曜ならば、来年の今日は火曜日です。
閏年直後の、平年の1月1日が月曜日である基準年(ここでは1917年とします)からの今日までの日数を割り出し、7で割った値が、0なら日曜日だし、1ならば月曜日だし....6ならば土曜日です。
つまり、例えば11月1日が土曜日ならば、11月7日(7+0)日は金曜日で、11月8日(7+1)は土曜日で、11月9日(7+2)は日曜日で...というように、
基準日から数えて、7+0は前日の曜日、7+1で同じ曜日、7+2で次の曜日...
となるわけです。視野をずうっと広げて、ある基準年からの日数を7で割った余りが曜日となります。
ところで、すべてが平年ならば、1年1曜日ずれるので、1月1日が月曜日ならば、12月31日は必ず同じ曜日になり、次の年の1月1日は火曜です。つまり、(7+1)となるので、1917年から前年までの年数そのものが曜日のずれとなります。なにも、全ての日を計算する必要はないのです。さらに、その間に何回閏年があるかで、その分一日ずれるのでそれも曜日のずれになります。そして、もし、今日の日付の曜日を求めるならば、今年の1月1日から今日までの日数も曜日のずれになります。
まとめると
| yyyy年mm月dd日の曜日は、
( ( yyyy - 1917 ) + [ ( yyyy - 1917 ) / 4 ] + (yyyy/mm/ddのジュリアン日※) ) mod 7 |
で曜日コード(計算結果が 0=日曜日, 1=月曜日.... 6=土曜日)が求まります。
例 1997年11月24日
( (1997-1917) + [(1997-1917)/4] + 328 ) mod 7
=(80 + 20 + 328) mod 7
=(428) mod 7
=1
=Monday※ジュリアン日(通算日)はcvtdatで取り出せますよね。
ごめんなさいまだ試していません。リリアンデートなんて初めて知った。みなさん知ってました?
ウェブでありました。日付計算アルゴリズムを見てみて下さい。[2000-3-1]
これは簡単ですね。日付をキーにしてフィールドにコードを、0から6までセット(1から7でも可)するだけですね。休日コードや月別の開始営業日や最終営業日など、どんどんセットすると便利でしょう。CLPならば、RTV形式のコマンドを作れば、いちいちCALLしないでも日付属性を取り出せますね。ただし、RPGでは、QCMDEXCではRTVできないので、そのコマンドのCPPかなにかをCALLします。カレンダーファイルは便利なので、曜日計算とあわせて、目的別に使っています。
|
You are at K's tips-n-kicks of AS/400
|
|
|||
|
|