1ヶ月前に投稿

鉄道遅延情報のJSONを条件分岐で表示してみる

2021年10月21日

この記事は約 12 分で読めます。

4.5

「if文」と言うと
「もし○○だったら××する」的な
条件分岐を書くときに使いますが、
このif文で論理演算子を使うことで、
より複雑な条件式を定義することが
できるようです。

遅延ちえん情報の取得

先ずは遅延ちえん情報の取得から、
JavaScriptでJSONを外部から取得する際には
fetch() 命令が使えるそうです。

fetch() を用いた
JavaScriptが以下になります。

JavaScript (JS)

let url = "https://tetsudo.rti-giken.jp/free/delay.json";
fetch(url).then(function (response) {
  return response.json();
}).then(function (traindata) {
  for (let i = 0; i < traindata.length; i++) {
    const company = traindata[i].company;
    const name = traindata[i].name;
    if (company == "JR東日本" ||  company == "JR西日本") {
      const date = new Date(Number(traindata[i].lastupdate_gmt) * 1000);
      const nowTime = new Date();
      if ((nowTime.getTime() - date.getTime()) / 1000 / 60 < 15) {
        const day_week = ['日', '月', '火', '水', '木', '金', '土'];
        const day = day_week[date.getDay()];
        const lastupdated = date.getFullYear()
        + '/' + ('0' + (date.getMonth() + 1)).slice(-2)
        + '/' + ('0' + date.getDate()).slice(-2)
        + '【' + day + '】'
        + ' ' + ('0' + date.getHours()).slice(-2)
        + ':' + ('0' + date.getMinutes()).slice(-2)
        + ':' + ('0' + date.getSeconds()).slice(-2)
        + ' (JST)';
        const row = document.getElementById('delay_info').insertRow();
        row.insertCell().textContent = name;
        row.insertCell().textContent = company;
        row.insertCell().textContent = lastupdated;
      } 
    } 
  }
});

HTML

<table id="delay_info">
  <thead>
    <tr>
      <th>路線名</th>
      <th>鉄道会社名</th>
      <th>最終更新日時</th>
    </tr>
  </thead>
</table>

if文で論理演算子を使う

論理演算子とは、
プログラミング言語の条件分岐などに使われる
andやorなどの論理演算を指示するための演算子です。
この場合の論理とは、trueとfalseの2つの値のことだそうです。
そして、
tureとfalseの2つの値を扱い、
論理積(and)、論理和(or)、論理否定(not) の
3つの演算に使われるのが、
論理演算子です。

3つの論理演算子

演算子意味
&& : 論理積 (2つのアンパサンド)AND かつa && b
|| : 論理和 (2つの縦記号)OR またはa || b
 ! : 論理否定 (感嘆符)NOT ~でない!a
if (company == "JR東日本" ||  company == "JR西日本") {

上記 if文が論理演算子を使った
条件分岐になります。

JR東日本とJR西日本のみ
表示されます。

論理和演算子

論理和 (|| OR)ってヤツですが、
「1つでも正しかったらOKで、
全部ダメだったらダメだよ」的な
論理演算になります。

全体
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

上記表のように
「1つでも正しければOK」
みたいですね。

論理積演算子

 if (name == "山手線" &&  company == "JR東日本") {

上記は
論理積(&& AND)で、
JR東日本の山手線のみ
表示されます。
論理積は
全部正しいときだけOK、
それ以外はNGらしいので、
山手線に遅延がなければ、
何も表示されない解釈で良いのかな?

全体
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

注意点として、
AND && は OR || の前に実行します。
AND && 演算子の優先順位は
OR || よりも高いそうです。

論理否定演算子

論理否定(! NOT)は、
「OKだったらNG、NGだったらOKにする」
的な論理演算だそうです。
「逆にする」みたいですね。

条件式の「==」と「===」の意味

==」(イコールが2つ)は等価演算子で、
===」(イコールが3つ)は厳密等価演算子と
言われる演算子で、
どちらも値の比較をする演算子だそうです。

なぜ「=」を2つ続けるか?
これは「=」が1つでは
代入の意味になるそうです。
用語意味
== (等価演算子)右の値と左の値が同じか比べるときに使う演算子
=== (厳密等価演算子)右の値と左の値が同じか型(変数の種類)まで含めて比べるときに使う演算子
  • == (等価演算子)は、
    右側の値と左側の値は同じですか?
  • === (厳密等価演算子)は、
    右側の値と左側の値は、変数の型(変数の種類)まで含めて同じですか?

2つの日付の差を日付の差を「分」で出す

const date = new Date(Number(traindata[i].lastupdate_gmt) * 1000);

Number()

上記、「UNIX時間」を
日本標準時に変換の仕方を
学びましたが、
Number」オブジェクトについて
もう少し調べてみました。
Number」オブジェクトは
基本的に文字列や日付などの値を
「数値」に変換するようです。

console.log( 'date()= ' + Number(new Date()) ); // 日付

// 結果 date()= 1634671624452

日付データは、
Number」オブジェクトが自動的に
「経過ミリ秒」に換算した
数値を返してくれます。

getTime()

以下の getTime() のコードの
理解に苦しみました。

const date = new Date(Number(traindata[i].lastupdate_gmt) * 1000);
const nowTime = new Date();
if ((nowTime.getTime() - date.getTime()) / 1000 / 60 < 15) {

現在時間を取得したい時は new Date()を使い、
さらに getTime()を使うと基準時間からの
経過ミリ秒で時間を取得できるそうです。

const nowTime = new Date();

上記で現在時間を取得し、

if ((nowTime.getTime() - date.getTime()) / 1000 / 60 < 15) {

nowTime.getTime()で現在時間を
経過ミリ秒で取得、
date.getTime()でjsonの更新時間を
経過ミリ秒で取得して、

/ 1000 / 60 < 15

2つの時間のミリ秒の差を
割ることで、差を分に変換して、
「その差が15分以内に更新された
情報を表示するもの」と
理解しました。

const date1 = new Date('2021-10-20 10:00:00');
const date2 = new Date('2021-10-21 10:00:00');

const diff = date2.getTime() - date1.getTime();

console.log(diff / 1000); // 秒 (86400)

console.log(diff / 1000 / 60); // 分 (1440)

console.log(diff / 1000 / 60 / 60); // 時間 (24)

console.log(diff / 1000 / 60 / 60 / 24); // 日 (1)

その差を秒・分・時間などで出す場合、
上記のようにして取得できるようです。

ここまで辿り着くのに
なかなか難しかったです(汗

結果

鉄道遅延ちえん情報
路線名 鉄道会社名 最終更新日時
(参考)
1.鉄道遅延情報JSON : https://rti-giken.jp/fhc/api/train_tetsudo/
2.テーブル装飾CSSデザイン : https://ayaito.net/webtips/css/5876/
3.見出し装飾CSSデザイン : https://pulpxstyle.com/heading-design/

もしも差分が負の値だったら?

確かに、
2つの差を計算するときにいつでも
「新しい時間 – 古い時間」に
なるとは限らないですね。

以下のコードですが、
別に「date1」から「date2」を
引けばいいじゃん!

const date1 = new Date('2021-10-20 10:00:00');
const date2 = new Date('2021-10-19 10:00:00');

const diff = date2.getTime() - date1.getTime();

console.log(diff / 1000); // 秒 (-86400)

console.log(diff / 1000 / 60); // 分 (-1440)

console.log(diff / 1000 / 60 / 60); // 時間 (-24)

console.log(diff / 1000 / 60 / 60 / 24); // 日 (-1)

以下の感じでいいんじゃね!

const diff = date1.getTime() - date2.getTime();

・・・と思ったのですが・・・
ダメ?ですか?

Math.abs

調べてみると、
Math.abs メソッドを使うと
絶対値を求めることができるようです。

数の絶対値は零からの距離

出典 : 絶対値 – Wikipedia

絶対値とは、0からの距離で、
例えば「3」も「-3」も
0からの距離は「3」になり、
これを絶対値といいます。

Math.abs メソッドで絶対値を使うと、
値が「正」と「負」のいずれも等しく
経過した時間を取得できるようです。

const date1 = new Date('2021-10-20 10:00:00');
const date2 = new Date('2021-10-19 10:00:00');

const diff = date2.getTime() - date1.getTime();

console.log(Math.abs(diff) / 1000); // 秒 (86400)

console.log(Math.abs(diff)  / 1000 / 60); // 分 (1440)

console.log(Math.abs(diff)  / 1000 / 60 / 60); // 時間 (24)

console.log(Math.abs(diff)  / 1000 / 60 / 60 / 24); // 日 (1)

なるほどですね。
とても勉強になりました。

Math.abs以外で絶対値を取得する

更に調べてみると、
Math.abs()以外で絶対値を取得する方法が
ありました。

JavaScriptで絶対値を取得する
Math.abs()の問題点として、
Math.abs()は数値でない場合
NaNなどを返すことがあるようです。

const date1 = new Date('2021-10-20 10:00:00');
const date2 = new Date('2021-10-19 10:00:00');

const diff = date2.getTime() - date1.getTime();

const abs = function (val) {
  return val < 0 ? -val : val
}

console.log(abs(diff) / 1000); // 秒 (86400)

console.log(abs(diff)  / 1000 / 60); // 分 (1440)

console.log(abs(diff)  / 1000 / 60 / 60); // 時間 (24)

console.log(abs(diff)  / 1000 / 60 / 60 / 24); // 日 (1)

absメソッドは数値から
符号 (+、-) を除いた絶対値を返します。
要するに、3なら3、-3でも3が
返ってくるということ、
そこに着目した関数のようです。

const abs = function (val) {
  return val < 0 ? -val : val
}

三項演算子を用いた関数のようです。
三項演算子とは、
if~elseをコンパクトに書くときの演算子です。

中身を見ると、
valが0よりも小さい場合は-valを返し、
0よりも大きい場合は
そのままvalを返す仕組みですね。

絶対値を返すのだから
負でも正の値が表示される訳ですね。

なるほど、
こちらも勉強になりました。

参考文献

最後に

貴重なお時間を割き、
最後まで
ご高覧いただきまして
有難うございました

鉄道遅延情報のJSONを条件分岐で表示してみる