www.sekidou.com

2002/08/23

日記用のスクリプト

.

10月6日 17:19:52 JST 付送信のメールにて, 北村曉さん からよりスマートな方法を教えていただきました。以下にいただいたメールの内容(抜粋)をご紹介いたします。

『闇黒日記』10月6日分
http://members.jcom.home.ne.jp/w3c/omake/diary.html
からのリンク経由で、「日記用のスクリプト」を拝見しました。

その中にあった、前日の日付を生成する方法についてなのですが、プログラムを組んで計算しなくとも、[日付オブジェクト].getTime()の値(1970年1月1日0時0分0秒からのミリ秒数になります)から24*60*60*1000を引いた値を使って、新たに日付オブジェクトを作っても可能のようです。

//サンプルスクリプト
today = new Date();
yesterday = new Date(today.getTime()-24*60*60*1000);
youbi = new Array("日","月","火","水","木","金","土");

document.write(today.toString(),"<br>");
document.write(today.getFullYear(),"年",
	today.getMonth()+1,"月",
	today.getDate(),"日",
	youbi[today.getDay()],"曜日","<br><br>");

document.write(yesterday.toString(),"<br>");
document.write(yesterday.getFullYear(),"年",
	yesterday.getMonth()+1,"月",
	yesterday.getDate(),"日",
	youbi[yesterday.getDay()],"曜日","<br>");

(結果例)
Sun Oct 6 17:13:39 UTC+0900 2002
2002年10月6日日曜日
Sat Oct 5 17:13:39 UTC+0900 2002
2002年10月5日土曜日

※『とほほのJavaScriptリファレンス』を参考にしました
http://tohoho.wakusei.ne.jp/js/date.htm

簡潔な記述ではありますが,理屈(仕組み)もきちんと述べられていて大変わかりやすい説明をしていただきました。これを応用すればフォームにも利用できますね。もう少し時間ができたら,自分で書いたものもこれに倣って改良していく所存です。わざわざメールをくださった北村曉さんには,この場を借りて改めてお礼申しあげます。また北村さんがこのページをご覧になるきっかけを作ってくださった“闇黒日記”の作者であらせられる野嵜健秀さんにも感謝いたします。


最近,DTI から提供されている CGI の掲示板機能を使って(出来合でない)自分流の“日記ツール”もどきを作ってみたのだが(もっとも実用はしていないが),その際にスクリプトを書いたのでちょっとそれを紹介したい。もちろん,ご覧になってみて気に入ったのであれば,これらをご自身のリソースで使っていただいても構わない。なお,二つのスクリプトはそれぞれ外部の .js ファイルを用いている。


さて,ウェブ頁で日記を書くとなるとたいていは頁内の見出し部分等に日記の日付を入れることになろう。プロバイダが用意した CGI の処理(%date% など)でも日付を入れることはできるが,書式が選べなかったり,(後述する問題と同様に)日記をつけたい日付ではなく実際に書き込む(CGI を動かす)日付が入ってしまうという弱点がある。

かといっていちいち手でフォームに入力するのも煩わしく,やはり日付が自動的にフォーム内に入力されているほうが楽だろう。日付(の値)を取得してフォームに渡すのは JavaScript を使って容易にできるし,またそのようなスクリプト自体は珍しいものではなくウェブ上でも数多く紹介されている。ただ,僕はそれら既存のものを少々変更して,年月日すべてをひとつの input 要素に入れるのではなく,それぞれを個々の要素に分けた(下記参照)。これは,後述のもう一つのスクリプトと関係があるからだ。なお,月日が 1桁の場合に頭に 0を入れる処理などもあるが,そういったスクリプトが必要な場合は各自インターネット上の他のリソースを検索する等して参照されたい。

日付の自動入力 (today.js)

// 変数
var dtToday = new Date;
var Yr;
var Mn;
var Dt;
var Dy = new Array("日","月","火","水","木","金","土");
// 値の取得
Yr = dtToday.getFullYear();
Mn = dtToday.getMonth() + 1;
Dt = dtToday.getDate();
// HTML 記述
document.write("<input name='Year' size='7' value='"+Yr+"'>年 ");
document.write("<input name='Month' size='4' value='"+Mn+"'>月 ");
document.write("<input name='Date' size='4' value='"+Dt+"'>日 ");
document.write("<input name='Day' size='4' value='"+Dy[dtToday.getDay()]+"'>曜日 ");

ところがこれでは少々困ることが起こりうる。

例えば夜寝る前に日記を書くというのはごく自然なことであるが,ほんの少し夜更かしをして 24時を回る(=日付が変わる)と,フォームに自動入力される日付が本来日記を書こうとしてるそれの一日後になってしまうのだ。そうなると,フォームの日付をわざわざ手で入力し直さなくてはならない。これはむしろ不便だ。そこで考えたのが,(ボタンなりアンカーなりを)一回クリックするだけでフォーム内に入力されている日付を一日戻せないかということだ。JavaScript を使えば,期待した動作ができるだろうと考えた。

日にちと曜日の値を一つずつ戻せばいいのだが,コトはそう簡単ではない。まず,例えば当日が 8月 1日だとするとその前日を求めるために日にちの値を減らすだけでは 8月 0日 になってしまう。これではいけないので,その場合は月の値を一つ減らして日にちを当該月の末日にする(上記例では 7月 31日にする)必要がある。

しかしだ…… ここで大きな問題となるのは,ご存じのように,月末日が常に一定ではないということだ。具体的には,1,3,5,7,8,10,12の各月が大の月(31日)で,4,6,9,11の各月が小の月(30日),さらには 2月も小の月だが,これがもっと厄介なのは閏年 ――西暦年が 4の倍数(ただし 100の倍数を除く)と 400の倍数―― では 29日,平年 ――西暦年が 4の倍数以外と 100の倍数(ただし 400の倍数を除く)―― では 28日となるのである。これらを当該月の値を条件として振り分ける点には苦労した。結果的には,“月末日”という変数を作ってその値を原則 31 としつつ,各条件により値を減らすということにした。なお,値を減らすだけではダメという点では各年の 1月 1日も同様だが,こちらは月末日のようなややこしいこともないので(年の値を一つ減らして 12月 31日にすればいいわけだから)むしろ簡単である。また,曜日は値を減らすのではなく,当日の値を取得してそれに割り当てる文字列(下記例では漢字)を本来のものから一つずつずらすことで処理をした。

以下がそのスクリプトである。

日付を一日前に (yestrday.js)

ファイル名はとりあえず 8字以内にするため“yestrday”としてある。

function Prev() {
// 変数
var Yr;   // 現在年(閏年2月末日算出の際必要)
var pYr;  // 前の年
var pMn;  // 前の月
var pDt;  // 前の日
var pDy = new Array("土","日","月","火","水","木","金");  // 曜日(漢字)をずらして指定
var eDt;  // 月末日
// 値の取得
Yr = dtToday.getFullYear();       // 現在年の値を取得
pYr = dtToday.getFullYear() - 1;  // 前の年の値を取得
pMn = dtToday.getMonth();     // 前の月の値を取得
pDt = dtToday.getDate() - 1;  // 前の日の値を取得
eDt = 31;                     // 月末日・大の月(31日)
if (pMn == 4 || pMn == 6 || pMn == 9 || pMn == 11) { eDt -= 1; }    // 月末日・小の月(30日)
if (pMn == 2 && Yr%4 == 0) { eDt -= 2; }    // 閏年2月(29日)
else if (pMn == 2 && Yr%100 == 0) { eDt -= 3; }  // 100年毎平年2月(28日)
else if (pMn == 2 && Yr%400 == 0) { eDt -= 2; }  // 400年毎閏年2月(29日)
// さしあたりコンピュータは 1900年や 2100年を処理しないらしいので,無用か?
else if (pMn == 2) { eDt -= 3; }          // 平年2月(28日)

// 前の月の値が 1未満の場合は 前年12月31日 に
if (pMn < 1) {
document.nikki.Year.value = pYr;
document.nikki.Month.value = 12;
document.nikki.Date.value = 31;
document.nikki.Day.value = pDy[dtToday.getDay()]; }
// 前の日の値が 1未満の場合は 前月末日 に
else if (pDt < 1) {
document.nikki.Month.value = pMn;
document.nikki.Date.value = eDt;
document.nikki.Day.value = pDy[dtToday.getDay()]; }
// それ以外の場合は 日と曜日 のみ一日前に
else {
document.nikki.Date.value = pDt;
document.nikki.Day.value = pDy[dtToday.getDay()]; }
}

そして HTML に以下のように記述する。ここでは上記二つの JavaScript ファイルを当該 HTML ファイルと同じディレクトリに置くものとしてあるが,別の場所に置く場合はそのパスを指定すべし。またここでは“日付を戻す”スクリプトを紹介するための必要最小限のソースしか記述していないので,実際に用いる場合は必要に応じ,form 要素の action 属性には使用する(プロバイダ指定の)CGIURI を入れねばならないこと,他の属性(method や accesskey 等)も指定すべきこと,および textarea 要素等を作成すべきことは,いうまでもない。

HTML

<form name="nikki" action="/cgi-bin/example.cgi">
  <p><script type="text/javascript" src="today.js"></script>
  <noscript>
    <input name="Year" size="7" value="2002">年 
    <input name="Month" size="4" value="">月 
    <input name="Date" size="4" value="">日 
    <input name="Day" size="4" value="">曜日 
  </noscript>
  <script type="text/javascript" src="yestrday.js"></script>
  <noscript><br>“昨日の日付にする”は JavaScript が有効でないと使えません。</noscript>
  <input type="button" value="昨日の日付にする" onclick="Prev()" onkeypress="Prev()"></p>
</form>

これらを実際に記述してブラウザで表示させると,以下のようになる。当然ながら,ブラウザで JavaScript を有効にしていないと noscript 要素の記述が表示され“昨日の日付にする”は機能しなくなる。

ブラウザでの表示

いかがだろう,ボタン操作をするとちゃんと日付が一日戻るだろうか。ちなみに操作前の現在の日付はコンピュータで設定されているそれから渡される値なので,コンピュータの日付設定を(1月 1日や 3月 1日など)いろいろと変えて操作してみるときちんと動作するかがわかる。

僕の検索能力が至らないのかもしれないが,この“yestrday.js”ような動作をする既存のスクリプトは(少なくともインターネット上のリソースでは)見あたらなかったから,オリジナルということができようか。なにぶん(HTML はともかく)スクリプトはズブの素人なのでバグがあるかもしれないし,もっと効率的な記述方法があるかもしれないが,各自改良していただいてなおかつそれをフィードバックしていただければ幸いである。門外漢の僕ごときが今回わざわざこれらのスクリプトを公開した意義は,まさにそこにあるのだから。




2,529,922

http://www.sekidou.com/
制作者に連絡する