1970 年 1 月 1 日 (UTC) からの経過時間をミリ秒単位で保持しています。
new Date() で、つまり引数なしでインスタンスを生成した時の日時が保持されます。静的なものです。
引数を指定して、「いついつの時刻」のようなインスタンスも生成できます。
クリックした瞬間の時刻を表示します。ローカル時間です。OSから時刻とロケールとを取得していると思われます。
月は0-11の値をとりますので注意。ここではそのままですが、日本用には+1するだけです。
年 | 月 | 日 | 時 | 分 | 秒 | ミリ秒 |
- | - | - | - | - | - | - |
<p><button type="button" onclick="dispDate1('p0')">日時更新</button></p> <tr id="p0"> <td>-</td><td>-</td><td>-</td> <td>-</td><td>-</td><td>-</td><td>-</td> </tr> <script> function dispDate0(where) { var koko = document.getElementById(where); if (koko!=null){ var tds = koko.getElementsByTagName("td"); var now = new Date(); tds[0].firstChild.nodeValue = now.getFullYear(); tds[1].firstChild.nodeValue = now.getMonth(); tds[2].firstChild.nodeValue = now.getDate(); tds[3].firstChild.nodeValue = now.getHours(); tds[4].firstChild.nodeValue = now.getMinutes(); tds[5].firstChild.nodeValue = now.getSeconds(); tds[6].firstChild.nodeValue = now.getMilliseconds(); } } </script>
getDay()は曜日です。0-6です。
getの後ろにUTCを挟んで、getUTCHours()などとすると協定世界時の値になります。
時間がずれているために日、月、年が異なる場合もあるので、getUTCDate()など、それぞれ全部あります。
メソッド | 結果 | 説明 |
---|---|---|
m | v | d |
m | v | d |
m | v | d |
m | v | d |
getTimezoneOffset()は、なぜ進んでいるものをマイナスとしたかはわかりません。ローカルな時間からUTCを計算したい時に足す値という解釈になります。
<p><button type="button" onclick="dispDate1('p1')">日時更新</button></p> <table id="p1"> <tr><th>メソッド</th><th>結果</th><th>説明</th></tr> <tr><td>m</td><td>v</td><td>d</td></tr> <tr><td>m</td><td>v</td><td>d</td></tr> ..... <script> function dispDate1(where) { var koko = document.getElementById(where); if (koko!=null){ var tds = koko.getElementsByTagName("td"); var now = new Date(); var sow = Date.now(); var i=0; tds[i++].firstChild.nodeValue = "getDay()"; tds[i++].firstChild.nodeValue = now.getDay(); tds[i++].firstChild.nodeValue = "曜日です"; tds[i++].firstChild.nodeValue = "getHours()"; tds[i++].firstChild.nodeValue = now.getHours(); tds[i++].firstChild.nodeValue = "ローカルな時間です"; tds[i++].firstChild.nodeValue = "getUTCHours()"; tds[i++].firstChild.nodeValue = now.getUTCHours(); tds[i++].firstChild.nodeValue = "協定世界時(UTC)です。日本より9時間遅れています"; tds[i++].firstChild.nodeValue = "getTimezoneOffset()"; tds[i++].firstChild.nodeValue = now.getTimezoneOffset(); tds[i++].firstChild.nodeValue = "ローカルな時間とUTCの差を分で表したものです。+900が -540になります"; } } </script>
toTimeString()もtoLocaleTimeString()も、ローカルな時間です。表現の形式がその国や地域に合わせているかどうかの違いです。
対して、ISOやUTCは協定世界時です。
メソッド | 結果 | 説明 |
---|---|---|
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
<p><button type="button" onclick="dispDate2('p2')">日時更新</button></p> <table id="p2"> <tr><th>メソッド</th><th>結果</th><th>説明</th></tr> <tr><td>m</td><td>v</td><td>d</td></tr> <tr><td>m</td><td>v</td><td>d</td></tr> ..... <script> function dispDate2(where) { var koko = document.getElementById(where); if (koko!=null){ var tds = koko.getElementsByTagName("td"); var now = new Date(); var i=0; tds[i++].firstChild.nodeValue = "toString()"; tds[i++].firstChild.nodeValue = now.toString(); tds[i++].firstChild.nodeValue = "米国型表示 年月日時分秒"; tds[i++].firstChild.nodeValue = "toDateString()"; tds[i++].firstChild.nodeValue = now.toDateString(); tds[i++].firstChild.nodeValue = "米国型表示 年月日"; tds[i++].firstChild.nodeValue = "toTimeString()"; tds[i++].firstChild.nodeValue = now.toTimeString(); tds[i++].firstChild.nodeValue = "米国型表示 時分秒"; tds[i++].firstChild.nodeValue = "toLocaleString()"; tds[i++].firstChild.nodeValue = now.toLocaleString(); tds[i++].firstChild.nodeValue = "ロケールに従った表示 年月日時分秒"; tds[i++].firstChild.nodeValue = "toLocaleDateString()"; tds[i++].firstChild.nodeValue = now.toLocaleDateString(); tds[i++].firstChild.nodeValue = "ロケールに従った表示 年月日"; tds[i++].firstChild.nodeValue = "toLocaleTimeString()"; tds[i++].firstChild.nodeValue = now.toLocaleTimeString(); tds[i++].firstChild.nodeValue = "ロケールに従った表示 時分秒"; tds[i++].firstChild.nodeValue = "toISOString()"; tds[i++].firstChild.nodeValue = now.toISOString(); tds[i++].firstChild.nodeValue = "ISO規格の書き方でUTCを表示する"; tds[i++].firstChild.nodeValue = "toUTCString()"; tds[i++].firstChild.nodeValue = now.toUTCString(); tds[i++].firstChild.nodeValue = "UTCで年月日時分秒を表示する"; } } </script>
1970年1月1日 00:00:00.0 (UTC) からの経過時間というのを検証したい。
経過時間を 24*60*60*1000(=86400 dayとおく) で割った余りから時間を求めると、getUTCHours()の値と一致します。つまりgetTime()で得られる経過時間はUTC基準に間違いありません。
newで生成されるインスタンスはUTCの値を持っていて、getHours()などでローカル時間に変換していると考えられます。
基本がローカル基準であれば、getTimezoneOffset()が負の値なのも納得がいくところですが、そうではないようです。
メソッド or 計算法 | 結果 | 説明 |
---|---|---|
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
m | v | d |
<p><button type="button" onclick="dispDate3('p3')">日時更新</button></p> <table id="p3"> <tr><th>メソッド or 計算法</th><th>結果</th><th>説明</th></tr> <tr><td>m</td><td>v</td><td>d</td></tr> <tr><td>m</td><td>v</td><td>d</td></tr> ..... <script> function dispDate3(where) { var koko = document.getElementById(where); if (koko!=null){ var tds = koko.getElementsByTagName("td"); var now = new Date(); var sow = Date.now(); var i=0; var msec = now.getTime(); var day = 24*60*60*1000; var hour = 60*60*1000; var mint = 60*1000; tds[i++].firstChild.nodeValue = "msec = now.getTime()"; tds[i++].firstChild.nodeValue = msec; tds[i++].firstChild.nodeValue = "ミリ秒数"; tds[i++].firstChild.nodeValue = "Math.floor(msec / day)"; tds[i++].firstChild.nodeValue = Math.floor(msec/day); tds[i++].firstChild.nodeValue = "日"; tds[i++].firstChild.nodeValue = "Math.floor((msec % day) / hour)"; tds[i++].firstChild.nodeValue = Math.floor((msec%day)/hour); tds[i++].firstChild.nodeValue = "時間"; tds[i++].firstChild.nodeValue = "Math.floor(((msec % day) % hour) / mint)"; tds[i++].firstChild.nodeValue = Math.floor(((msec%day)%hour)/mint); tds[i++].firstChild.nodeValue = "分"; tds[i++].firstChild.nodeValue = "(((msec % day) % hour) % mint) / 1000"; tds[i++].firstChild.nodeValue = (((msec%day)%hour)%mint)/1000; tds[i++].firstChild.nodeValue = "秒"; tds[i++].firstChild.nodeValue = "getUTCHours()"; tds[i++].firstChild.nodeValue = now.getUTCHours(); tds[i++].firstChild.nodeValue = "協定世界時(UTC)です。上記の「時間」に一致するはずです"; tds[i++].firstChild.nodeValue = "getHours()"; tds[i++].firstChild.nodeValue = now.getHours(); tds[i++].firstChild.nodeValue = "ローカルな時間です。JSTは+9時間です"; tds[i++].firstChild.nodeValue = "Date.now()"; tds[i++].firstChild.nodeValue = sow; tds[i++].firstChild.nodeValue = "ミリ秒数を得るだけなら、new Date() しない方法もあります"; } } </script>
-
スタート後、できるだけ正確に5秒でストップしてください
スタート時とストップ時のDate.now()の値から間隔を計算します
<p><button id="tmsw" type="button" onclick="tmstart()" style="vertical-align:text-bottom">スタート</button> <span id=tmrs style="font-size:150%;">-</span></p> <p id=tmcomm>スタート後、できるだけ正確に5秒でストップしてください</p> <script> var tmstarttime; function tmstart() { tmstarttime = Date.now(); var koko = document.getElementById("tmsw"); koko.setAttribute("onclick","tmstop()"); koko.firstChild.nodeValue = "ストップ"; document.getElementById("tmrs").firstChild.nodeValue = "?"; var comm = document.getElementById("tmcomm"); comm.firstChild.nodeValue = "できるだけ正確に5秒でストップしてください"; } function tmstop() { var tmstoptime = Date.now(); var koko = document.getElementById("tmsw"); koko.setAttribute("onclick","tmstart()"); koko.firstChild.nodeValue = "スタート"; var tmdiff = tmstoptime-tmstarttime; document.getElementById("tmrs").firstChild.nodeValue = tmdiff/1000; var tmdiff5 = 5000-tmdiff; if (0>tmdiff5) tmdiff5 = -tmdiff5; var commtext = "差は "+tmdiff5/1000+"秒 "; if(tmdiff5==0) commtext += "ぴったりです"; else if(10>tmdiff5) commtext += "驚異的に正確です"; else if(100>tmdiff5) commtext += "とても正確です"; else if(500>tmdiff5) commtext += "かなり正確です"; var comm = document.getElementById("tmcomm"); comm.firstChild.nodeValue = commtext; } </script>
new Date()に引数を与えて、ある時刻を保持したインスタンスを生成できます。
引数は3種あって、(1)1970-1-1(UTC) からのミリ秒数、(2)日付を表す文字列値、(3)年月日時分秒ミリ秒をコンマで区切ったものです。
(1)はこれまでのことからgetTime()で得られるようなUTCだろうと思います。
(2)はtoString()やtoLocaleString()で示された形式が使えるのだろうと思いますが、タイムゾーンの指定ができるかどうかを含め面倒そうなので、ここでは調べません。
(3)は、2018,0,21など、必要な所までを可変長引数で入れられるので(多分2つ以上で(3)と判断される)、これを使っていくことにします。月は0から11まで、日はなぜか1から、時分秒は省略すると0と解釈されます。
(3)の指定はローカル時間で指定したことになります。しかし、インスタンスにはUTCの値が入ります。つまり11時と指定すれば9時間前の2時の値が入ります。これを以下で確認します。
メソッド or 計算法 | 結果 | 説明 |
---|---|---|
mv | ||
m | v | v |
m | v | v |
m | v | v |
m | v | v |
m | v | v |
m | v | v |
mv | ||
m | v | v |
m | v | v |
m | v | v |
m | v | v |
m | v | v |
m | v | v |
m | v | v |
<script> function dispDate4(where) { var koko = document.getElementById(where); if (koko!=null){ var tds = koko.getElementsByTagName("td"); var now = new Date(); var i=0; var h11 = new Date(2000,4,5,11,22,33); var msec = h11.getTime(); var day = 24*60*60*1000; var hour = 60*60*1000; var mint = 60*1000; tds[i++].firstChild.nodeValue = "h11=new Date(2000,4,5,11,22,33); day=24*60*60*1000; 等とする"; tds[i++].firstChild.nodeValue = "msec=h11.getTime()"; tds[i++].firstChild.nodeValue = msec; tds[i++].firstChild.nodeValue = "ミリ秒数"; tds[i++].firstChild.nodeValue = "Math.floor(msec / day)"; tds[i++].firstChild.nodeValue = Math.floor(msec/day); tds[i++].firstChild.nodeValue = "日"; tds[i++].firstChild.nodeValue = "Math.floor((msec % day) / hour)"; tds[i++].firstChild.nodeValue = Math.floor((msec%day)/hour); tds[i++].firstChild.nodeValue = "時間 (UTCの値が入っている)"; tds[i++].firstChild.nodeValue = "Math.floor(((msec % day) % hour) / mint)"; tds[i++].firstChild.nodeValue = Math.floor(((msec%day)%hour)/mint); tds[i++].firstChild.nodeValue = "分"; tds[i++].firstChild.nodeValue = "(((msec % day) % hour) % mint) / 1000"; tds[i++].firstChild.nodeValue = (((msec%day)%hour)%mint)/1000; tds[i++].firstChild.nodeValue = "秒"; tds[i++].firstChild.nodeValue = "h11.getHours()"; tds[i++].firstChild.nodeValue = h11.getHours(); tds[i++].firstChild.nodeValue = "ローカル時間に戻して返す"; var h08 = new Date(2000,4,5,8); msec = h08.getTime(); tds[i++].firstChild.nodeValue = "h08=new Date(2000,4,5,8)として同様に"; tds[i++].firstChild.nodeValue = "msec=h08.getTime()"; tds[i++].firstChild.nodeValue = msec; tds[i++].firstChild.nodeValue = "ミリ秒数"; tds[i++].firstChild.nodeValue = "Math.floor(msec / day)"; tds[i++].firstChild.nodeValue = Math.floor(msec/day); tds[i++].firstChild.nodeValue = "日 (1日前になっている)"; tds[i++].firstChild.nodeValue = "Math.floor((msec % day) / hour)"; tds[i++].firstChild.nodeValue = Math.floor((msec%day)/hour); tds[i++].firstChild.nodeValue = "時間 (UTCの値が入っている 8-9は23時)"; tds[i++].firstChild.nodeValue = "Math.floor(((msec % day) % hour) / mint)"; tds[i++].firstChild.nodeValue = Math.floor(((msec%day)%hour)/mint); tds[i++].firstChild.nodeValue = "分"; tds[i++].firstChild.nodeValue = "(((msec % day) % hour) % mint) / 1000"; tds[i++].firstChild.nodeValue = (((msec%day)%hour)%mint)/1000; tds[i++].firstChild.nodeValue = "秒"; tds[i++].firstChild.nodeValue = "h08.getDate()"; tds[i++].firstChild.nodeValue = h08.getDate(); tds[i++].firstChild.nodeValue = "日はローカル時間に戻して5日を返す"; tds[i++].firstChild.nodeValue = "h08.getHours()"; tds[i++].firstChild.nodeValue = h08.getHours(); tds[i++].firstChild.nodeValue = "時間もローカル時間に戻して返す"; } } </script>
new Date()に引数を与えて使う例として、年齢の計算をあげてみます。
2000年1月21日生まれの人は、2018年1月21日で18歳となります。今日の日付を20,21,22と切り替えてうまく計算できることを確認してください。
計算法 | 計算過程 | 結果 |
---|---|---|
m | v | v |
m | v | v |
m | v | v |
m | v | v |
<p><button type="button" onclick="dispDate5('p5','20')">20日の年齢</button> <button type=button onclick="dispDate5('p5','21')">21日の年齢</button> <button type=button onclick="dispDate5('p5','22')">22日の年齢</button></p> <table id=p5> <tr><th>計算法</th><th>計算過程</th><th>結果</th></tr> <tr><td>m</td><td>v</td><td>v</td></tr> ... <script> function dispDate5(where,when) { var koko = document.getElementById(where); if (koko!=null){ var tds = koko.getElementsByTagName("td"); var now = new Date(2018,0,when); var i=0; var birth = new Date(2000,0,21); //var msec = h11.getTime(); var day = 24*60*60*1000; var hour = 60*60*1000; var mint = 60*1000; tds[i++].firstChild.nodeValue = "年の部分の差を求める"; tds[i++].firstChild.nodeValue = now.getFullYear()+"-"+birth.getFullYear(); var nennosa = now.getFullYear()-birth.getFullYear(); tds[i++].firstChild.nodeValue = nennosa; tds[i++].firstChild.nodeValue = "年を同じにセットして(誕生日-指定日)"; tds[i++].firstChild.nodeValue = now.setFullYear(2018)+"-"+birth.setFullYear(2018); var hinosa = birth.setFullYear(2018)-now.setFullYear(2018); var d = (birth.setFullYear(2018)>now.setFullYear(2018))?1:0; tds[i++].firstChild.nodeValue = hinosa; tds[i++].firstChild.nodeValue = "誕生日が来ていなければ1を引く必要あり"; tds[i++].firstChild.nodeValue = "誕生日>指定日 なら 1, "; tds[i++].firstChild.nodeValue = d; tds[i++].firstChild.nodeValue = "2018年1月"+when+"日の年齢は"; tds[i++].firstChild.nodeValue = nennosa+"-"+d; tds[i++].firstChild.nodeValue = nennosa-d; } } </script>
javascriptには年齢を計算する仕組みがありません。誕生日と現在の時間の2つのインスタンスを作ってそこから計算することを考えます。
インスタンスはローカル時間で作成しますが、内部的にはUTCで値を保持します。例では誕生日を2000年1月21日生まれとして、new Date(2000,0,21) で生成しています。これは、new Date(2000,0,21,0,0,0,0)と同じです。これが日本時間の環境で行われると、UTCでは2000-1-20 21:00:00.0となり、日付が変わってしまいますが、心配いりません。もしも、現在時間が 2018年1月20日23時に生成すると new Date(2018,0,20,23) で生成されますが、UTCでは2000-1-20 14:00:00.0となり誕生日前と判断できます。
計算方法としては、ミリ秒を引き算してしまってはだめです。1年の秒数が閏年のために一定ではないので計算が厄介になります。getFullYear()を使って引き算をすると、現在の月日が今年の誕生日を過ぎていれば年齢に一致します。過ぎているかどうかを2つのインスタンスの"年"をsetFullYear(2018)などとして同じ年にしてミリ秒を比べることで判断することができます。誕生日を過ぎていなければ年から計算した値から1を引けば年齢になります。