1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

気象庁サイトを利用したビューアの作成 6 地震情報

1
Posted at

目次・全体的な注意点(第1回の記事)

気象庁は天気予報のほかに、地震や火山の情報も発表しています。今回は、地震情報を表示するページを作成してみます

地震情報について

気象庁では、地震が発生すると時間の経過に応じて地震に関する情報を発表していきます。比較的頻繁に発表される情報には以下のようなものがあります

  • 緊急地震速報
    地震発生数秒後に、最初の揺れを全国の観測網でいち早く検知し、これから揺れが来る地域にいち早くお知らせする情報です

  • 震度速報
    地震発生約1分半後に、震度3以上を観測した地域を速報します。全国をおよそ200に分けた地域名で発表します

  • 震源に関する情報
    地震発生約3分後に、地震発生地震の発生場所(震源)の位置や深さ、マグニチュード、津波のありなしを発表します

  • 震源・震度情報
    地震発生約5分後に、震度1以上を観測した市町村や地点を発表します

今回は、これらを表示するビューアーを作成していきます

apiのURL

他の情報と同様、ブラウザの開発者ツールでネットワークタブを開いた状態で目的のページにアクセスし、Fetch/XHRでフィルタするとデータを格納したファイルが見つかります

最近発生した地震のリストは、 https://www.jma.go.jp/bosai/quake/data/list.json に格納されています

個別の地震の情報は、 https://www.jma.go.jp/bosai/quake/data/{jsonName}.json に格納されています。{jsonName}の部分は個々の地震によって異なり、list.json内に地震ごとのファイル名が格納されています

apiの構造

気象庁ホームページの内部apiの構造は、気象庁防災情報XMLの構造をモデルとしているものが多いです。このため、気象庁防災情報XMLの解説資料が参考になる場合が多いです

地震・津波・火山関連の電文の説明は「地震火山関連_解説資料.pdf」としてまとめられており、この資料の内容が参考になります

地震リスト(list.json)

このapiは略称を多用しており少々読み取りづらいですが、解説資料の内容から以下のように推測できます

要素名 説明
{i}.ctt 発信時刻(ConTrol/daTetime)? 20260404194051
{i}.eid EventID 20260404193655
{i}.rdt 発表時刻(ReportDateTime) 2026-04-04T19:40:00+09:00
{i}.ttl 標題(head/Title) 震源・震度情報
{i}.ift 情報形態(InfoType) 発表 or 訂正 or 取消
{i}.ser 情報番号(Serial) 1
{i}.at 地震検知時刻(ArrivalTime) 2026-04-04T19:36:00+09:00
{i}.anm 震央地名(Area/Name) 宮城県沖
{i}.acd 震央地名コード(Area/Code) 287
{i}.cod 震源座標(Coordinate) +38.4+141.9-60000/
{i}.mag マグニチュード(Magnitude) 4.9
{i}.maxi 最大震度(MaxInt=MaximumIntensity) 3
{i}.int 各地の震度
{i}.int.{j} 各地の震度(都道府県ごと) {"code":"03","maxi":"3","city":[]}
{i}.int.{j}.city.{k} 各地の震度(市町村ごと) {"code":"0320300","maxi":"3"}
{i}.json 個別地震のjsonファイル名 20260404194051_20260404193655_VXSE5k_1.json

EventIDは同一の地震を判定する際の参考になりますが、必ずしも一連の地震で同じIDが割り振られるとは限らないことに注意が必要です。大半の場合は一致しますが、緊急地震速報や震度速報は迅速性重視の自動処理のため、地震が頻発した際などにうまくIDの結合ができない場合もあります。このため、必ずIDが揃うという前提で処理を行わないよう注意が必要です

例)
地震Aの震度速報が発表(ID:A)

直後に地震Bが続発し地震Bの震度速報が発表(ID:B)

同一の地震であったことが分かり震源・震度情報に両方の震度を含めて発表(ID:A)

このような場合には、ID:Bの震度速報に対応した震源・震度情報は発表されないように見えますので、見せ方には注意が必要です

震央地名は震央の緯度経度ごとに一定の地域名が定められています

震源座標はISO 6709形式で記載されています。"+38.4+141.9-60000/"なら、北緯38.4度、東経141.9度、深さ60kmを表します。南緯/西経の場合はマイナスとなります。深さはごく浅い(5km未満)場合には+0表記となります。震源の一部や全部の要素が不明の場合は "+37.5+138.6/""" となる場合があります

MaxIntは震度1では"1"、震度2で"2"、……、震度7で"7"となります。震度5弱/5強/6弱/6強は"5-""5+""6-""6+"となります

各地の震度は地域コードで示されており、そのままでは市町村名などを読み取ることができませんが、天気予報等の地域コードファイル https://www.jma.go.jp/bosai/common/const/area.json と地震情報と天気予報の地名対照用のファイル https://www.jma.go.jp/bosai/common/const/earthquake_area.json から読み取ることができます。また、個別の地震情報のjsonファイル内ではコードだけでなく名称でも格納されているため、そちらを読むことでも名称が取得できます

個別の地震情報({jsonName}.json)

こちらは解説資料におおむね準拠した要素名が振られています

要素名 説明
Head.Title 標題 震源・震度情報
Head.ReportDateTime 発表時刻 2026-04-01T10:22:00+09:00
Head.EventID EventID 20260401100625
Head.Headline.Text 見出し文 1日10時06分ころ、地震がありました。
Body.Earthquake.OriginTime 地震発生時刻 2026-04-01T10:06:00+09:00
Body.Earthquake.ArrivalTime 地震検知時刻 2026-04-01T10:06:00+09:00
Body.Earthquake.Hypocenter.Area.Name 震央地名 茨城県南部
Body.Earthquake.Hypocenter.Area.Coordinate 震央座標 +36.1+140.0-50000/
Body.Earthquake.Magnitude マグニチュード 5.0
Body.Earthquake.Intensity.Observation 震度
Body.Comments.ForecastComment.Text 固定付加文 この地震による津波の心配はありません。\nこの地震について、緊急地震速報を発表しています。
Body.Comments.VarComment.Text 固定付加文(その他) *印は気象庁以外の震度観測点についての情報です。
Body.Comments.FreeFormComment 自由付加文

震度の部分は以下のように 都道府県>地域>市町村>観測点 の入れ子構造となっています

"Observation":{
  "MaxInt":"5-",
  "Pref":[
    {
      "Name":"栃木県", "Code":"09", "MaxInt":"5-",
      "Area":[
        {
          "Name":"栃木県南部", "Code":"311", "MaxInt":"5-",
          "City":[
            {
              "Name":"真岡市", "Code":"0920900", "MaxInt":"5-",
              "IntensityStation": [
                {
                  "Name":"真岡市石島*", "Code":"0920933", "Int":"5-", "latlon":{ "lat":36.39, "lon": 139.97}
                },{
                  "Name":"真岡市田町*", "Code":"0920920", "Int":"4", "latlon":{ "lat":36.44, "lon":140.02}
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

震度の部分は稀に"震度5弱以上未入電"となる場合があります。これは、周辺の震度から震度5弱以上と想定される地点から震度のデータが入ってきていないことを表します

表示用のコード

ここまでの内容を表に起こしていきます

地震一覧

各震度用の背景色を定義しておきます。震度ごとの色は気象庁ホームページの配色指針を参考にしました

<style>
  *{ font-family:sans-serif;}
  table, tr, td, th{ border-collapse:collapse; white-space:nowrap; text-align:center;}
  th,td{ padding:2px 8px; border-style:solid; border-width:1px 0; border-color:#d8d8db;}
  th{ background-color:#f1f1f4;}
  td.i7 { background:#b40068; color:white;}
  td.i6p{ background:#a50021; color:white;}
  td.i6m{ background:#ff2800; color:white;}
  td.i5p{ background:#ff9900; color:black;}
  td.i5m{ background:#ffe600; color:black;}
  td.i4 { background:#fae696; color:black;}
  td.i3 { background:#0041ff; color:white;}
  td.i2 { background:#00aaff; color:black;}
  td.i1 { background:#f2f2ff; color:black;}
</style>

地震発生時刻(at)をapiから読み取ります(地震の電文は種類によって要素があったりなかったりするため、今回のサンプルでは要素の存在確認を頻繁に行っています。仕様書をしっかり読んだらもっとシンプルに書けるんでしょうが……)

if( report['at']==undefined){
  out += "<td></td>";
}else{
  let arrivalTime = Temporal.ZonedDateTime.from( report['at']+"[Asia/Tokyo]");
  out += "<td>" + dateFormat(arrivalTime,'m/d h:n') + "</td>";
}

震源(anm)をapiから読み取ります。震度速報や南海トラフ地震関連情報ではanmは空欄となり、何の情報か分からなくなるため、anmが定義されていない場合はttl(情報名)を表示するようにします

if( report['anm']==undefined || report['anm']==""){
  if( report['ttl']==undefined){
    out += "<td></td>";
  }else{
    out += "<td>(" + report['ttl'] + ")</td>"; // infoType
  }
}else{
  out += "<td>" + report['anm'] + "</td>"; // areaName
}

最大震度(maxi)を読み取ります。震度に応じて背景色を変えるようにします

if( report['maxi']==undefined){
  out += "<td></td>";
}else{
  out += "<td class='i" + report['maxi'].replace("-","m").replace("+","p") + "'>" + report['maxi'] + "</td>"; // maxInt = maximumIntensity
}

この後作る個別の地震情報ページへのリンクを作成します。(個別の地震情報ページを気象庁ホームページで代替する場合は、https://www.jma.go.jp/bosai/map.html#elem=int&contents=earthquake_map&id={eid}(通常版)またはhttps://www.data.jma.go.jp/multi/quake/quake_detail.html?eventID={eid}&lang=jp(多言語版)へのリンクを貼ると良いでしょう)

if( report['json']==undefined){
  out += "<td></td>";
}else{
  out += "<td><a href='./quake.html?json=" + report['json'] + "'>詳細</a></td>";
}

個別の地震情報

URLパラメータから個別の地震のjsonファイル名を読み取ります

const params = new URLSearchParams(window.location.search);

function get(){
  fetch("https://www.jma.go.jp/bosai/quake/data/" + params.get("json"))
  .then((response) => response.json())
  .then((report) => display(report));
}

震源の深さを読み取ります。だいぶガバガバですが、深さを+または-のある位置で区切って、3番目(深さに当たる部分)を読み取り、0の場合には「ごく浅い」、その他の場合は「○○キロ」と表示するアルゴリズムとします

let coordinate = report['Body']['Earthquake']['Hypocenter']['Area']['Coordinate'];
if( coordinate!=undefined){
  coordinate = coordinate.split(/(?=[-+])/); 
  if( coordinate.length>=3){
    let depth = coordinate[2].replace("/","") / 1000 * (-1);
    if( depth==0){
      out += "<tr><th>深さ</th><td>" + "ごく浅い</td></tr>";
    }else{
      out += "<tr><th>深さ</th><td>" + depth + "キロ</td></tr>";
    }
  }
}

付加文を読み取ります。Body.Comments配下のVarCommentやForecastCommentを一律で読み取る設計とします

if( report['Body']['Comments']!=undefined){
  out += "<tr><th></th><td>";
  for( let commentType in report['Body']['Comments']){
    if( report['Body']['Comments'][commentType]['Text']!=undefined){
      out += report['Body']['Comments'][commentType]['Text'].replaceAll("\n","<br>") + "<br>";
    }
  }
  out += "</td></tr>";
  if( report['Body']['Comments']['FreeFormComment']!=undefined){
    out += "<tr><th></th><td>" + report['Body']['Comments']['FreeFormComment'].replaceAll("\n","<br>") + "</td></tr>";
  }
}

地域ごと・市町村ごと・観測点ごとの震度を読み取って集約します。今回は、地域ごとの震度は最大震度別にまとめ、市町村ごと・観測点ごとの震度は最大震度別・府県別にまとめるようにしました

let ints = {"area":{},"city":{},"obs":{}};
for( let pref of report['Body']['Intensity']['Observation']['Pref']){
  let prefName = pref['Name'];
  for( let area of pref['Area']){
    let areaName = area['Name'], areaInt = area['MaxInt'];
    if( ints['area'][areaInt]==undefined){
      ints['area'][areaInt] = [];
    }
    ints['area'][areaInt].push( areaName);
    if( area['City']==undefined){
      continue;
    }
    for( let city of area['City']){
      let cityName = city['Name'], cityInt = city['MaxInt'];
      if( ints['city'][cityInt]==undefined){
        ints['city'][cityInt] = [];
      }
      if( ints['city'][cityInt][prefName]==undefined){
        ints['city'][cityInt][prefName] = [];
      }
      ints['city'][cityInt][prefName].push( cityName);
      for( let obs of city['IntensityStation']){
        let obsName = obs['Name'], obsInt = obs['Int'];
        if( ints['obs'][obsInt]==undefined){
          ints['obs'][obsInt] = {};
        }
        if( ints['obs'][obsInt][prefName]==undefined){
          ints['obs'][obsInt][prefName] = [];
        }
        ints['obs'][obsInt][prefName].push( obsName);
      }
    }
  }
}

観測された震度を高いほうから表にまとめていきます。地域ごとの震度は単に地域名を並べ、市町村ごと・観測点ごとの震度は都道府県ごとに表にまとめるようにしました

  const intsArray = ["7", "6+", "6-", "5+", "震度5弱以上未入電", "5-", "4", "3", "2", "1"];
  const areaInfos = {"area":"地域","city":"市町村","obs":"観測点"};
  for( let areaType of ['area','city','obs']){
    if( Object.keys(ints[areaType]).length==0){
      continue;
    }
    out += "<tr><th>" + areaInfos[areaType] + "ごとの震度</th><td>";
    for( let int of intsArray){
      if( ints[areaType][int]==undefined){
        continue;
      }
      out += "<p>";
      out += "<span class='i" + int.replace("震度5弱以上未入電","5m").replace("+","p").replace("-","m") + "'>";
      out += "震度" + int.replace("-","").replace("+","").replace("震度5弱以上未入電","5弱以上と推定されるが未受信/精査中");
      out += "</span> ";
      if( areaType=="area"){
        for( let areaName of ints[areaType][int]){
          out += areaName + " ";
        }
        out += "<br>";
      }else{
        out += "<table>";
        for( let prefName in ints[areaType][int]){
          out += "<tr><th>" + prefName + "</th><td>";
          for( let areaName of ints[areaType][int][prefName]){
            out += areaName + " ";
          }
          out += "</td></tr>";
        }
        out += "</table>";
      }
      out += "</p>";
    }
    out += "</td></tr>";
  }
}

表示ページ全体のソースコード

サンプルページ
サンプルページ(Date APIを利用した版)

地震リスト

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>地震情報(一覧)</title>
  <style>
    *{ font-family:sans-serif;}
    table, tr, td, th{ border-collapse:collapse; white-space:nowrap; text-align:center;}
    th,td{ padding:2px 8px; border-style:solid; border-width:1px 0; border-color:#d8d8db;}
    th{ background-color:#f1f1f4;}
    td.i7 { background:#b40068; color:white;}
    td.i6p{ background:#a50021; color:white;}
    td.i6m{ background:#ff2800; color:white;}
    td.i5p{ background:#ff9900; color:black;}
    td.i5m{ background:#ffe600; color:black;}
    td.i4 { background:#fae696; color:black;}
    td.i3 { background:#0041ff; color:white;}
    td.i2 { background:#00aaff; color:black;}
    td.i1 { background:#f2f2ff; color:black;}
  </style>
</head>
<body>
  <h1>地震情報(一覧)</h1>
  <div id="out"></div>
  <script>
    "use strict";

    get();

    function get(){
      fetch("https://www.jma.go.jp/bosai/quake/data/list.json")
      .then((response) => response.json())
      .then((reports) => display(reports));
    }

    function display( reports){
      let out = "";

      out += "<table><tr><th>発生時刻</th><th>震源</th><th>震度</th><th>詳細</th></tr>";
      for( let report of reports){
        out += "<tr>";
        if( report['at']==undefined){
          out += "<td></td>";
        }else{
          let arrivalTime = Temporal.ZonedDateTime.from( report['at']+"[Asia/Tokyo]");
          out += "<td>" + dateFormat(arrivalTime,'m/d h:n') + "</td>";
        }
        if( report['anm']==undefined || report['anm']==""){
          if( report['ttl']==undefined){
            out += "<td></td>";
          }else{
            out += "<td>(" + report['ttl'] + ")</td>"; // infoType
          }
        }else{
          out += "<td>" + report['anm'] + "</td>"; // areaName
        }
        if( report['maxi']==undefined){
          out += "<td></td>";
        }else{
          out += "<td class='i" + report['maxi'].replace("-","m").replace("+","p") + "'>" + report['maxi'] + "</td>"; // maxInt = maximumIntensity
        }
        if( report['json']==undefined){
          out += "<td></td>";
        }else{
          out += "<td><a href='./quake.html?json=" + report['json'] + "'>詳細</a></td>";
        }
        out += "</tr>";
      }
      out += "</table>";
      document.getElementById("out").innerHTML = out;
    }

    function dateFormat( t, f='y-m-dTh:n:s', is24=false){ // for Temporal
      const j=["","","","","","","",""];const e=["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
      if(is24&&t.hour==0){t.substract({days:1});f=f.replace(/h/g,"24").replace(/H/g,24);}
      const y=t.year,m=t.month,d=t.day,h=t.hour,n=t.minute,s=t.second,w=t.dayOfWeek;
      f=f.replace(/y/g,("000"+y).slice(-4)).replace(/Y/g,y).replace(/m/g,("0"+m).slice(-2)).replace(/M/g,m).replace(/d/g,("0"+d).slice(-2)).replace(/D/g,d);
      f=f.replace(/w/g,j[w]).replace(/W/g,e[w]);
      f=f.replace(/h/g,("0"+h).slice(-2)).replace(/H/g,h).replace(/n/g,("0"+n).slice(-2)).replace(/N/g,n).replace(/s/g,("0"+s).slice(-2)).replace(/S/g,s);
      return f;
    }
  </script>
</body>
</html>

個別の地震情報

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>地震情報</title>
  <style>
    *{ font-family:sans-serif;}
    table, tr, td, th{ border-collapse:collapse;}
    th,td{ padding:2px 8px; border-style:solid; border-width:1px 0; border-color:#d8d8db;}
    th{ background-color:#f1f1f4; white-space:nowrap;}
    span.i7 { background:#b40068; color:white;}
    span.i6p{ background:#a50021; color:white;}
    span.i6m{ background:#ff2800; color:white;}
    span.i5p{ background:#ff9900; color:black;}
    span.i5m{ background:#ffe600; color:black;}
    span.i4 { background:#fae696; color:black;}
    span.i3 { background:#0041ff; color:white;}
    span.i2 { background:#00aaff; color:black;}
    span.i1 { background:#f2f2ff; color:black;}
    em{ font-style:normal; background:#ffff80;}
    p{ margin-top:16px; margin-bottom:0;}
  </style>
</head>
<body>
  <h1>地震情報</h1>
  <div id="out"></div>
  <script>
    "use strict";
    const params = new URLSearchParams(window.location.search);


    get();

    function get(){
      fetch("https://www.jma.go.jp/bosai/quake/data/" + params.get("json"))
      .then((response) => response.json())
      .then((report) => display(report));
    }

    function display( report){
      let out = "";

      let reportDatetime = Temporal.ZonedDateTime.from( report['Head']['ReportDateTime']+"[Asia/Tokyo]");
      out += "<table>";
      out += "<tr><th>情報名</th><td>" + report['Head']['Title'] + "</td></tr>";
      out += "<tr><th>発表時刻</th><td>" + dateFormat(reportDatetime,'y/m/d h:n') + " " + report['Head']['InfoType'] + "</td></tr>";
      if( report['Body']['Earthquake']!=undefined){
        if( report['Body']['Earthquake']['OriginTime']!=undefined){
          let originTime = Temporal.ZonedDateTime.from( report['Body']['Earthquake']['OriginTime']+"[Asia/Tokyo]");
          out += "<tr><th>発生時刻</th><td>" + dateFormat(originTime,'d日h時n分') + "ごろ</td></tr>";
        }
        if( report['Body']['Earthquake']['Hypocenter']!=undefined){
          if( report['Body']['Earthquake']['Hypocenter']['Area']!=undefined){
            out += "<tr><th>震源</th><td>" + report['Body']['Earthquake']['Hypocenter']['Area']['Name'] + "</td></tr>";
            let coordinate = report['Body']['Earthquake']['Hypocenter']['Area']['Coordinate'];
            if( coordinate!=undefined){
              coordinate = coordinate.split(/(?=[-+])/); 
              if( coordinate.length>=3){
                let depth = coordinate[2].replace("/","") / 1000 * (-1);
                if( depth==0){
                  out += "<tr><th>深さ</th><td>" + "ごく浅い</td></tr>";
                }else{
                  out += "<tr><th>深さ</th><td>" + depth + "キロ</td></tr>";
                }
              }
            }
          }
        }
        if( report['Body']['Earthquake']['Magnitude']!=undefined){
          out += "<tr><th>マグニチュード</th><td>" + report['Body']['Earthquake']['Magnitude'] + "</td></tr>";
        }
      }
      if( report['Body']['Comments']!=undefined){
        out += "<tr><th></th><td>";
        for( let commentType in report['Body']['Comments']){
          if( report['Body']['Comments'][commentType]['Text']!=undefined){
            out += report['Body']['Comments'][commentType]['Text'].replaceAll("\n","<br>") + "<br>";
          }
        }
        out += "</td></tr>";
        if( report['Body']['Comments']['FreeFormComment']!=undefined){
          out += "<tr><th></th><td>" + report['Body']['Comments']['FreeFormComment'].replaceAll("\n","<br>") + "</td></tr>";
        }
      }
      if( report['Body']['Intensity']!=undefined && report['Body']['Intensity']['Observation']!=undefined && report['Body']['Intensity']['Observation']['Pref']!=undefined){
        let ints = {"area":{},"city":{},"obs":{}};
        for( let pref of report['Body']['Intensity']['Observation']['Pref']){
          let prefName = pref['Name'];
          for( let area of pref['Area']){
            let areaName = area['Name'], areaInt = area['MaxInt'];
            if( ints['area'][areaInt]==undefined){
              ints['area'][areaInt] = [];
            }
            ints['area'][areaInt].push( areaName);
            if( area['City']==undefined){
              continue;
            }
            for( let city of area['City']){
              let cityName = city['Name'], cityInt = city['MaxInt'];
              if( ints['city'][cityInt]==undefined){
                ints['city'][cityInt] = [];
              }
              if( ints['city'][cityInt][prefName]==undefined){
                ints['city'][cityInt][prefName] = [];
              }
              ints['city'][cityInt][prefName].push( cityName);
              for( let obs of city['IntensityStation']){
                let obsName = obs['Name'], obsInt = obs['Int'];
                if( ints['obs'][obsInt]==undefined){
                  ints['obs'][obsInt] = {};
                }
                if( ints['obs'][obsInt][prefName]==undefined){
                  ints['obs'][obsInt][prefName] = [];
                }
                ints['obs'][obsInt][prefName].push( obsName);
              }
            }
          }
        }
        const intsArray = ["7", "6+", "6-", "5+", "震度5弱以上未入電", "5-", "4", "3", "2", "1"];
        const areaInfos = {"area":"地域","city":"市町村","obs":"観測点"};
        for( let areaType of ['area','city','obs']){
          if( Object.keys(ints[areaType]).length==0){
            continue;
          }
          out += "<tr><th>" + areaInfos[areaType] + "ごとの震度</th><td>";
          for( let int of intsArray){
            if( ints[areaType][int]==undefined){
              continue;
            }
            out += "<p>";
            out += "<span class='i" + int.replace("震度5弱以上未入電","5m").replace("+","p").replace("-","m") + "'>";
            out += "震度" + int.replace("-","").replace("+","").replace("震度5弱以上未入電","5弱以上と推定されるが未受信/精査中");
            out += "</span> ";
            if( areaType=="area"){
              for( let areaName of ints[areaType][int]){
                out += areaName + " ";
              }
              out += "<br>";
            }else{
              out += "<table>";
              for( let prefName in ints[areaType][int]){
                out += "<tr><th>" + prefName + "</th><td>";
                for( let areaName of ints[areaType][int][prefName]){
                  out += areaName + " ";
                }
                out += "</td></tr>";
              }
              out += "</table>";
            }
            out += "</p>";
          }
          out += "</td></tr>";
        }
      }
      out += "</table>";
      document.getElementById("out").innerHTML = out;
    }

    function dateFormat( t, f='y-m-dTh:n:s', is24=false){ // for Temporal
      const j=["","","","","","","",""];const e=["","Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
      if(is24&&t.hour==0){t.substract({days:1});f=f.replace(/h/g,"24").replace(/H/g,24);}
      const y=t.year,m=t.month,d=t.day,h=t.hour,n=t.minute,s=t.second,w=t.dayOfWeek;
      f=f.replace(/y/g,("000"+y).slice(-4)).replace(/Y/g,y).replace(/m/g,("0"+m).slice(-2)).replace(/M/g,m).replace(/d/g,("0"+d).slice(-2)).replace(/D/g,d);
      f=f.replace(/w/g,j[w]).replace(/W/g,e[w]);
      f=f.replace(/h/g,("0"+h).slice(-2)).replace(/H/g,h).replace(/n/g,("0"+n).slice(-2)).replace(/N/g,n).replace(/s/g,("0"+s).slice(-2)).replace(/S/g,s);
      return f;
    }
  </script>
</body>
</html>
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?