Home > イヌでもわかるJavaScript講座 お品書き
イヌでもわかるJavaScript講座 お品書き へ戻ります
イヌでもわかるJavaScript講座


Step.19 - 誕生日から経過日を計算する


年月日を入力して何日経ったかを計算します。
自分が生まれて何日過ぎたか知っている人は結構少ないと思います(誰も知らんわー)。


Step テーマ
● getTime (経過時間)

実行例


生年月日 (西暦)



リスト


<script type="text/javascript"><!--
function mySet(){
    myNow = new Date();
    myBirth = new Date( document.myF.myFy.value, document.myF.myFM.value-1, document.myF.myFd.value );
    myMsec = myNow.getTime() - myBirth.getTime();
    myDay = Math.floor( myMsec / (1000*60*60*24) );
    document.myF.myFmes.value = "生まれてから " + (myDay+1) + "日目になります";
}
// --></script>

<form name="myF">生年月日 (西暦)
<input type="text" size="4" name="myFy">年
<input type="text" size="2" name="myFM">月
<input type="text" size="2" name="myFd">日
<input type="button" value="OK" onclick="mySet()"><br><br>
<input type="text" size="50" name="myFmes">
</form>


サンプルだけの HTMLは こちらへ

説明


さて、指定日から何日過ぎたかを計算しようとすると、みなさんはどう考えるでしょう。
今日の年から指定の年を引いて 365を掛けようとすると、うるう年が邪魔してくれます。

Date() オブジェクトには、getTime() というメソッドがあります。
これは、1970/01/01 00:00:00.000 からの 通算ミリ秒(経過ミリ秒) を返してくれます。1970年以前でしたら、マイナス値になります。
これを使えば、うるう年は気にしなくて よさそうです。
※ IE3 は 1970年以前は扱えません。

Step.3 とかで 現在日時の取得は、以下のようにしていました。
myNow = new Date();

Date() のパラメータに、年、月、日を渡すと、指定された日時の情報を取得することができます。
myBirth = new Date( 年, 月-1, 日 );

よって、
myMsec = myNow.getTime() - myBirth.getTime();
とすれば、現在の 経過ミリ秒から 誕生日の経過ミリ秒を引けば、誕生日からの経過ミリ秒が計算できます。
※ myBirthの Date()の パラメータは 年月日のみで 時分秒を省略しているので、00:00:00 になります。

myDay = Math.floor( myMsec / (1000*60*60*24) );
これで、ミリ秒を日に置き換えます。1000ミリ秒*60秒*60分*24時間、つまり一日です。
※ 素直に myMsec / 86400000 と記述しても、もちろん OKですが プログラムは人間、計算はコンピュータにやらせましょう。というのは私の考え (^^; 。
Math.floor() は 小数点切捨てです ※ Step.6 参照

document.myF.myFmes.value = "生まれてから " + (myDay+1) + "日目になります";
生まれた日を 1日と数えたいので、myDay に 1 を足しています。

(myDay+1) の括弧は 決して省略してはいけません。
数値+数値 と、文字+文字 の違いは、もうご存知と思います。文字+数値のとき、数値は文字の数字に変換されてしまいます。
つまり、"あ" + 1 + 2 は、"あ12" になってしまいます。
※ ちなみに、1 + 2 + "あ" + 1 + 2 は、"3あ12" です。


ちょっと補足しておきます。

getTime() は、1970/01/01 00:00:00.000 からの 経過ミリ秒です と上で書いております。
では、
myDate = new Date( 1970 , 0 , 1 );
myMsec = myDate.getTime( );

の myMsec の値はいくらでしょう?
当然、ゼロでしょう と思います。



さて、どんな数値が表示されていますか?
私の PCでは、-32400000 と表示されました。

32400000 / 1000 = 32400(秒)
32400 / 60 = 540(分)
540 / 60 = 9(時間)
私の PCは9時間誤差がでました。

この getTime() は、GMT時間です。
GMT時間とは、グリニッジ標準時(Greenwich Mean Time)、経度0度の子午線における 平均太陽時なんです。 ・・・で? (-o-メ
イギリスはロンドン南東部のテムズ川南岸の その子午線の通るところに グリニッジ天文台が置かれていたんです。(^^; ・・・で? (-o-メ
1884年に ワシントンの国際会議で、本初子午線に指定され 経度および時刻の原点となっているんです。(ToT) ・・・だからなんだ? (-o-メ
私のコンピュータの国設定が 日本 に設定されているんです。(ToT)  ・・・いったいさっきから何が言いたいんだ! (-o-メ

日本(ローカル時間)が 1970/01/01 00:00 の時、GMT時間は 時差で 9時間前の 1969/12/31 15:00 なんです。(ToT)
・・・それをはやく言わんか!このバカタレが!(-o-メ



参考ステップ
Step.3 現在の日付と時間を表示してみましょう
Step.18 誕生日の曜日を取得してみましょう
Step.48 実施日から何日経過したかカウントアップしてみましょう
Step.49 予定日まであと何日かカウントダウンしてみましょう
Step.69 来年へのカウントダウンを表示してみましょう
Step.91 本日の行事を表示してみましょう
Step.97 明日の行事を表示してみましょう

Q&A


[Q] 「今日で●才●ヶ月●日になりました」と表示したいのですが。
[A] 今日から誕生日を引けば、よろしいかと。

↓↓↓↓↓↓↓↓↓↓ 間違ったサンプル・説明 ここから ↓↓↓↓↓↓↓↓↓↓
生年月日 (西暦)
<FORM name="myFormAge">生年月日 (西暦)
<INPUT type="text" size="4" name="myAgeY">年
<INPUT type="text" size="2" name="myAgeM">月
<INPUT type="text" size="2" name="myAgeD">日
<INPUT type="button" value="OK" onclick="myAge()"><br>
<INPUT type="text" size="50" name="myAgeMes">
</FORM>
<script type="text/javascript"><!--

function myAge(){
   myNow = new Date();
   myBirth = new Date( document.myFormAge.myAgeY.value, document.myFormAge.myAgeM.value-1, document.myFormAge.myAgeD.value );
   myBirth.setTime(myNow.getTime() - myBirth.getTime());
   myYear = myBirth.getFullYear() - 1970;
   myMonth = myBirth.getMonth();
   myDate = myBirth.getDate();
   document.myFormAge.myAgeMes.value = "あんたの歳は "+myYear+"才 "+myMonth+"ヶ月と "+myDate+"日目";
}
// --></SCRIPT>

今日から誕生日を引いた通算秒をDateオブジェクトにセットします。
そいつの「年」を「歳」、「月」を「ヶ月」、「日」を「日目」をして使います。
うーん、それで良いかどうかは、現在、酔っ払っているため判断不能です。やばいケースがあればメールくださいませ。
ちなみに「日」は今日も1日と数えています。
↑↑↑↑↑↑↑↑↑↑ 間違ったサンプル・説明 ここまで ↑↑↑↑↑↑↑↑↑↑

↓↓↓↓↓↓↓↓↓ 提供いただいたサンプル・説明 ここから ↓↓↓↓↓↓↓↓↓
生年月日 (西暦)
<FORM name="myFormAge">生年月日 (西暦)
<INPUT type="text" size="4" name="myAgeY">年
<INPUT type="text" size="2" name="myAgeM">月
<INPUT type="text" size="2" name="myAgeD">日
<INPUT type="button" value="OK" onclick="myAge()"><br;>
<INPUT type="text" size="50" name="myAgeMes">
</FORM>
<script type="text/javascript"><!--
function myAge(){

   //現在から、誕生日を引き、基準日に足す
   //つまり、現在から、誕生日の日にち分の時間だけ引く
   myNow = new Date();
   myBirth = new Date( 1970, 0, document.myFormAge.myAgeD.value );
   myBirth.setTime( myNow.getTime() - myBirth.getTime() );

   //求めた年月日から基準日を引く
   myYear = myBirth.getUTCFullYear() - document.myFormAge.myAgeY.value;
   myMonth = myBirth.getUTCMonth() - (document.myFormAge.myAgeM.value - 1);
   if(myMonth < 0){ //月がマイナスなので年から繰り下げ
     myYear --;
     myMonth += 12;
   }
   myDate = myBirth.getUTCDate();

   document.myFormAge.myAgeMes.value = "あんたの歳は "+myYear+"才 "+myMonth+"ヶ月と "+myDate+"日目";
}
// --></SCRIPT>

Step19のQ&Aにあります、「今日で●才●ヶ月●日になりました」という表示についてですが、
やばいケースと思われるものがありますので、お知らせいたします。


通常、誕生日から何ヶ月経ったとする場合、異なる月の同じ日を指すと思います。
そう考えますと、掲載されているコードでは、誕生日から現在までの時間を、1970年1月1日に足し、そこから年月日で求めているため、1月生まれの人以外は、何日目かがずれてしまいます。

問題例:
2006年11月6日生まれの人は、今日(2007年1月6日)は、2ヶ月と1日目であるはずだが、表示は2ヶ月と3日目。

原因:
2006年11月は30日、2006年12月は31日の61日で2ヶ月のはずが、1970年1月は31日、1970年2月が28日の59日で2ヶ月となるため。


また、1970年はうるう年ではないため、1月生まれの人であっても、現在がうるう年であり、3月の同日を過ぎている場合に、何日目かがずれてしまいます。
最もひどい場合だと、才まで繰り上がってしまいます。

問題例:
2004年1月1日生まれの人は、2004年12月31日では、11ヶ月と31日目であるはずだが、表示は1才0ヶ月と1日目。

原因:
1970年は365日だが、2004年は366日あるため。

これらの問題を回避するためには、月の日数の誤差を、正しく計算する必要があります。
そこでまず、基準日を1970年1月1日ではなく、入力された誕生日と「同じ年」「同じ月」の「1日」にします。
次に、誕生日から現在までの時間を、基準日に足します。
これは、現在から、入力された日にちだけ引いたものと同じになります。
これで、月による日数の誤差が吸収されます。
最後に、求めた年月日から基準日を引いたものが答えになります。
月がマイナスとなった場合は、1年は必ず12ヶ月ですので、年から繰り下げることが可能です。

補足:
入力された日数を引き算する部分ですが、
Date(1970,0,document.myFormAge.myAgeD.value)
がUTCですので、
getFullYear()、getMonth()、 getDate() ではなく、
getUTCFullYear()、getUTCMonth()、getUTCDate() を使って、時差を考慮しています。

↑↑↑↑↑↑↑↑↑ 提供いただいたサンプル・説明 ここまで ↑↑↑↑↑↑↑↑↑

ソースとわかりやすい説明文の提供ありがとうございました。そのまま掲載させていただきました。Thanks:Kさん

【教訓】飲酒時は判断能力が低下するため、車の運転とプログラミングは避けましょう。


 
イヌでもわかるJavaScript講座 お品書き へ戻ります