NLP（日本語）で使えるJSのDateライブラリを公開しました

# はじめに

NLPでDateを操作できるJavaScript向けのOSSを作って、githubとCDNに公開しました。

「…NLPって何？」と思われたかと思いますが、
「自然言語解析（Natural Language Processing）」のことです。

|区別|言語|
|---|---|
|機械が理解できる言語|マシン語（0と1の羅列）|
|人間が読み書きできて、機械も理解できる言語|プログラミング言語|
|人間が普段しゃべっている言葉|自然言語|

機械の言葉は人間には理解できず、人間の言葉も機械には理解できません。
だから、人間と機械の共通言語としてプログラミング言語ができました。

ですが、今は機械が人間の言葉を直接理解する場面が身近にあります。
たとえば、アレクサ、Siri、翻訳サイト、Google検索だってそうです。

【スマートスピーカーの場合】
人間が言葉で話しかける　→　機械が理解　→　何か処理をする
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/5db8e18a-b348-4719-9363-d95873c1a37d.png" width=40%>

この「人間の言葉を理解する仕組み」が自然言語解析と呼ばれています。

# NLPでJavaScriptの日時を操作する

アレクサに話しかける感じで、自然言語でプログラミングがしたい。
そう思って、JavaScript向けのライブラリを作って公開しました。

### これまで（JavaScript標準）の日時操作

これまでの「プログラミング言語」の日時操作はこうでした。

```javascript
let date = new Date();
date.setDate(date.getDate() + 1); // 明日の
date.setHours(12 + 3); // 午後3時
date.setMinutes(12); // 12分
date.setSeconds(10); // 10秒
```

setDateは日を設定、一文字違いのsetDayは曜日、setMonthだけは0から始まる、みたいなルールがありました。
文字列にするなら、そこからさらにフォーマッターで変換して…みたいなことをしていました。
ソースは長く、学習コストがかかり、可読性もいまいちです。

### NLPでの日時操作

自然言語ではこう書きます。

```javascript
// textには"令和3年01月11日 03時12分10秒"が入ります
let text = NLPDate("明日の午前3時12分10秒").asString("和暦の年月日時分秒");
```

日本語で書いた文章が、そのままJavascriptで使えるデータになります。
ソースは短く、日本語さえできれば学習コストはゼロ、可読性も高くなります。

### NLPDateの使い方

現在日時を取るには、「現在」を渡して、asDateで取得結果をDate型にキャストします。

```javascript
// new Date()と同じ現在日時が取れます
let date = NLPDate("現在").asDate();
```

3時間後の現在時間を取るには、「現在から3時間後」と書くだけです。

```javascript
// new Date()から3時間後の日時が取れます
let date = NLPDate("現在から3時間後").asDate();
```

「次の火曜日の午後3時20分」と書けば、今日は月曜ですから、明日の午後3時20分が取れます。

```javascript
// Mon Jan 11 2021 08:15:52 GMT+0900 (日本標準時)の時に実行すると、
// Tue Jan 12 2021 15:20:00 GMT+0900 (日本標準時)の時間になります。
let date = NLPDate("次の火曜日の午後3時20分").asDate();
```

「現在から3時間後の四日後の20秒後、それから五年後」などと操作を続けることもできます。もちろん現在以外の日時を操作したり、同じ単位への操作を続けて、「明日の今頃から3時間後の3時間後の4時間後の7時間後」などと書くこともできます。

```javascript
// Mon Jan 11 2021 08:10:23 GMT+0900 (日本標準時)の時に実行すると、
// Thu Jan 15 2026 11:10:43 GMT+0900 (日本標準時)の時間になります。
let date = NLPDate("現在から3時間後の四日後の20秒後、それから五年後").asDate();

// Mon Jan 11 2021 08:08:33 GMT+0900 (日本標準時)の時に実行すると、
// Wed Jan 13 2021 01:08:33 GMT+0900 (日本標準時)の時間になります
let date = NLPDate("明日の今頃から3時間後の3時間後の4時間後の7時間後").asDate();
```

Date型ではなく文字列でほしいのなら、asStringでキャストします。
ほしいフォーマットを自然な日本語で書けば、そのフォーマットになります。

```javascript
// 日本語のフォーマットの文字列になります
// textには、"2021年07月30日 08時26分42秒"が入ります
let text = NLPDate("2021年7月30日の今頃").asString("日本語の年月日時分秒");
```

何も指定しなければISO8601形式になります。

```javascript
// ISO8601のフォーマットの文字列になります
// textには、"2021-07-30T00:00:00+09:00"が入ります
let text = NLPDate("2021年7月30日").asString();
```

ほかの日時と比較したいのなら、asNumberで数値にキャストするのが便利です。

```javascript
let date = NLPDate("現在");
if (NLPDate("2020年1月").asNumber("年月") <= date.asNumber("年月") &&
    date.asNumber("年月") < NLPDate("2020年8月").asNumber("年月")) {
    // 2020年8月のasNumber("年月")は202008になります。
    // 数値でとるので、if文で大小比較ができます
    console.log("今日は2020年1月～2020年7月末までの間です");
}
```

### あいまいな表現

「2021年2月の第三水曜日の午後３時」のように、
漢数字、半角数字、全角数字の表記ゆれがあっても正常に動作します。

```javascript
// date には"2021-02-17T15:00:00+09:00"のDateオブジェクトが入ります
let date = NLPDate("2021年2月の第三水曜日の午後３時").asDate();
```

うろ覚えになっても、名前が半分あっていれば正常に判定します。

```javascript
// "ISO8601"がうろ覚えですが、正常に解析します。
// date には"2021-07-31T00:00:00+09:00"の文字列が入ります。
let date = NLPDate("2021年7月30日の月末").asString("INO8688");
```

一部に日時が入っていれば、日時だけを読み取ります。

```javascript
// date には"2021-01-12T00:00:00+09:00"のDateオブジェクトが入ります
let date = NLPDate("ふるさと納税　ワンストップ特例申請に関する申請期限（令和３年１月１２日）などを掲載しました。").asDate();
```

最後のキスは煙草のフレーバーがしました、泣いているのはいつでしょう。

```javascript
// date には"2021-01-11T20:56:24+09:00"のDateオブジェクトが入ります
let date = NLPDate("明日の今頃には私はきっと泣いている").asDate();
```

たぶん君が来るのは2分後です。

```javascript
// date には"2021-01-10T02:00:00+09:00"のDateオブジェクトが入ります
let date = NLPDate("午前2時、踏切に、望遠鏡を担いでった").asDate();
```

人間の言葉で書けると、ぐっと簡単になる感じがしないでしょうか。

使い方はシンプルで、覚えるメソッドは3つだけです。自然言語で日時を作ったあと、その結果が文字列型でほしいのなら「asString」、数値でほしいのなら「asNumber」、Date型でほしいのなら「asDate」を使って変換します。

## 導入して使ってみる

NLPDateは、ブラウザ、node、コマンドプロンプト、bashで使えます。
ライブラリのサイズは40KBほどで、ローカルに保存すればオフラインで使えます。

### ソースコード

NLPDateのレポジトリはこちらにあります。
https://github.com/ShotaOki/NLPDate

実際にブラウザで動かしているサンプルがこちらにあります。
https://shotaoki.github.io/NLPDate.github.io/

### ブラウザに導入する

CDNで読み込ませることができます。
以下のテキストを HTML のヘッダに置いてください。

```html
<script src="https://cdn.jsdelivr.net/gh/ShotaOki/NLPDate@v0.0.1/modern/nlpdate-main.min.js"></script>
```

※もし IE11 で動かす必要があれば、上のリンクの代わりにこちらを置いてください。

```html
<!-- ES2015版：新しいブラウザのほか、IE11でも動きます。通常版よりもファイルサイズが大きくなります -->
<script src="https://cdn.jsdelivr.net/gh/ShotaOki/NLPDate@v0.0.1/es2015/nlpdate-main.min.js"></script>
```

### コマンドプロンプトやbashに導入する

githubからプロジェクトをCloneしたあと、「${Cloneしたフォルダ}/bin」にパスを通します。
コマンドプロンプトやbashから使えるようになります。

```bash
nlp-date "平成元年1月15日の今頃" -f "スラッシュ区切りの年月日時分秒"
>> 1989/01/15 21:34:29
```

# おわりに

まだしばらくバグ取りや安定化の時間が必要だと思います。

自然言語でプログラミングができたら楽だ、ソースも読みやすくなる、と思ってくださる方がおられましたら、こちらのライブラリを覚えておいていただくか、フィードバックや参加をいただけないかと思っています。

ぜひ今後ともよろしくお願いいたします。