概要
仕事で、日時の変換を頻繁にする必要があり、毎回ツールを探すのが大変だったので、自分で作ってみることにしてみました。
方針としては、気軽に使えるようにすること。そのため、HTMLにしています。コピーすれば社内とかでも気軽に使えるようになるので。
また、UI系はあまり気にしなくてもいいBootstrapで、日付変換のライブラリは、Luxonにしています。
moment.jsを使おうとしたけど、いつの間にかメンテナンスモードになっていたので、その代替として選んだ。ほかにもあったが、Timezoneの処理がよさそうだったので使ってます。
開発環境
- Windows11
- VSCode
- JavaScript、CSSライブラリ
- Bootstrap 5
- UIライブラリ
- 久々に触って手間取った。あと、ネット検索でバージョン5の情報があまり乗ってなかった。
- Luxon 3
- 日時変換のライブラリ
- Bootstrap 5
使い方
特徴として、Unix時間とMongoDBのObjectIDの変換がよくあるので、それらを変換できるようにしています。初期表示では、入力ボックスに現在の日時が表示されるようになっています。
変換ボタンを押すことで、入力された日付を変換して、出力にある形式に変換します。
コード
日付変換ツールのすべてのソースコードです。各種ライブラリは、CDNを指定していますので、コピーするだけで使用可能です。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
<title>日時変換ツール</title>
</head>
<body>
<div class="container">
<p class="h1 mt-3">日時変換ツール</p>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label for="input-format">自由フォーマット</label>
<div class="input-group">
<input type="text" class="form-control" id="input-format">
<input type="text" class="form-control" id="input-format-text" value="yyyy/MM/dd HH:mm:ss">
<select class="form-select" id="input-format-zone">
<option value="Asia/Tokyo">Asia/Tokyo</option>
<option value="UTC">UTC</option>
</select>
<div class="input-group-append">
<button class="btn btn-outline-primary" onclick="javascript:convertFormat()">変換</button>
</div>
</div>
<small class="form-text text-muted">指定されたフォーマットの日付</small>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label for="input-unixtime">Unixtime</label>
<div class="input-group">
<input type="text" class="form-control" id="input-unixtime">
<div class="input-group-append">
<button class="btn btn-outline-primary" onclick="javascript:convertFormat()">変換</button>
</div>
</div>
<small class="form-text text-muted">10桁(秒)、13桁(ミリ秒)のUnix時間</small>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label for="input-iso">ISO</label>
<div class="input-group">
<input type="text" class="form-control" id="input-iso">
<div class="input-group-append">
<button class="btn btn-outline-primary" onclick="javascript:convertISO()">変換</button>
</div>
</div>
<small class="form-text text-muted">国際標準化機構(ISO)の日付。ISO8601準拠</small>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label for="input-rfc2822">RFC2822</label>
<div class="input-group">
<input type="text" class="form-control" id="input-rfc2822">
<div class="input-group-append">
<button class="btn btn-outline-primary" onclick="javascript:convertRFC2822()">変換</button>
</div>
</div>
<small class="form-text text-muted">インターネットメールの日時形式。RFC2822互換。</small>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label for="input-http">HTTP</label>
<div class="input-group">
<input type="text" class="form-control" id="input-http">
<div class="input-group-append">
<button class="btn btn-outline-primary" onclick="javascript:convertHTTP()">変換</button>
</div>
</div>
<small class="form-text text-muted">HTTPヘッダーのGTMの日付。RFC1123に準拠。</small>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="form-group">
<label for="input-objectid">ObjectId</label>
<div class="input-group">
<input type="text" class="form-control" id="input-objectid">
<div class="input-group-append">
<button class="btn btn-outline-primary" onclick="javascript:convertObjectId();">変換</button>
</div>
</div>
<small class="form-text text-muted">Mongo DBのObjectId</small>
</div>
</div>
</div>
<p class="h3 mt-5 mb-4 border-bottom border-secondary"><i class="bi bi-download"></i>出力</p>
<div class="d-grid gap-2 col-6 mx-auto">
<button class="btn btn-outline-primary mb-4" onclick="javascript:outputAll()">現在日時</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">形式</th>
<th scope="col">値</th>
</tr>
</thead>
<tbody>
<tr>
<td>日本時間: yyyy/MM/dd hh:mm:ss</td>
<td id="output-format"></td>
</tr>
<tr>
<td>Unixtime(秒)</td>
<td id="output-unixtime"></td>
</tr>
<tr>
<td>ISO(JST)</td>
<td id="output-iso"></td>
</tr>
<tr>
<td>RFC2822</td>
<td id="output-rfc2822"></td>
</tr>
<tr>
<td>HTTP</td>
<td id="output-http"></td>
</tr>
<tr>
<td>ObjectId</td>
<td id="output-objectid"></td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/luxon@3.0.1/build/global/luxon.min.js"
integrity="sha256-uQ0RrcqAQ8NxzNqZH11eXx3qFLAgwEgSQN1V0N1+UlM=" crossorigin="anonymous"></script>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
outputAll()
inputAll()
})
function outputFormat(dt) {
setText("output-format", dt.toFormat("yyyy/MM/dd HH:mm:ss", { zone: 'Asia/Tokyo', }))
setText("output-unixtime", dt.toUnixInteger())
setText("output-iso", dt.toISO())
setText("output-rfc2822", dt.toRFC2822())
setText("output-http", dt.toHTTP())
setText("output-objectid", toObjectId(dt))
}
function inputFormat(dt) {
setValue("input-format", dt.toFormat("yyyy/MM/dd HH:mm:ss"))
setValue("input-unixtime", dt.toUnixInteger())
setValue("input-iso", dt.toISO())
setValue("input-rfc2822", dt.toRFC2822())
setValue("input-http", dt.toHTTP())
setValue("input-objectid", toObjectId(dt))
}
function inputAll() {
var dt = now()
inputFormat(dt)
}
function outputAll() {
var dt = now()
outputFormat(dt)
}
function toObjectId(dt) {
return Math.floor(dt.toUnixInteger()).toString(16) + "0000000000000000";
}
function fromObjectId(str) {
return parseInt(str.substring(0, 8), 16)
}
function getText(id) {
return document.getElementById(id).textContent
}
function setText(id, text) {
document.getElementById(id).textContent = text
}
function setValue(id, text) {
document.getElementById(id).value = text
}
function getValue(id) {
return document.getElementById(id).value
}
function now() {
var DateTime = luxon.DateTime;
var dt = DateTime.now().setZone("Asia/Tokyo")
return dt
}
function convertUnixtime() {
var DateTime = luxon.DateTime;
var str = getValue("input-unixtime")
if (/\d{1,10}/.test(str)) {
outputFormat(DateTime.fromSeconds(parseInt(str, 10)))
} else if (/\d{11,13}/.test(str)) {
outputFormat(DateTime.fromMills(parseInt(str, 13)))
}
}
function convertISO() {
var DateTime = luxon.DateTime;
var str = getValue("input-iso")
outputFormat(DateTime.fromISO(str))
}
function convertRFC2822() {
var DateTime = luxon.DateTime;
var str = getValue("input-rfc2822")
outputFormat(DateTime.fromRFC2822(str))
}
function convertHTTP() {
var DateTime = luxon.DateTime;
var str = getValue("input-http")
outputFormat(DateTime.fromHTTP(str))
}
function convertFormat() {
var DateTime = luxon.DateTime;
var str = getValue("input-format")
var format = getValue("input-format-text")
var z = getValue("input-format-zone")
outputFormat(DateTime.fromFormat(str, format, { zone: z }))
}
function convertObjectId() {
var DateTime = luxon.DateTime;
var str = getValue("input-objectid")
outputFormat(DateTime.fromSeconds(fromObjectId(str)))
}
</script>
</body>
</html>
まとめ
リファクタリングできるところはありますが、作業に時間がかかりすぎたので、いったん公開してほそぼそ修正していきます。
gitに挙げるのと、コピー機能を付けたり、UI的にも出力部分をもうちょっとできたかなぁと思えるので。
やっぱり、デザイン系は難しいと再認識したのと、時間がかかるので、JavaScriptをモジュールっぽく書かなくてよかった(初心者にはわかりやすいしね)と思う今日この頃。。。
コメント