Kinx ライブラリ - DateTime

# DateTime

## はじめに

**「見た目は JavaScript、頭脳(中身)は Ruby、（安定感は AC/DC）」** でお届けしているスクリプト言語 [Kinx](https://github.com/Kray-G/kinx)。言語はライブラリが命。ということでライブラリの使い方編。 

今回は DateTime です。Range でも使えるようにしました。

* 参考
    * 最初の動機 ... [スクリプト言語 KINX（ご紹介）](https://qiita.com/Kray-G/items/ca08b6fb40d15dd0ec76)
        * 個別記事へのリンクは全てここに集約してあります。
    * リポジトリ ... [https://github.com/Kray-G/kinx](https://github.com/Kray-G/kinx)
        * Pull Request 等お待ちしております。 

## 使い方

### using DateTime

DateTime ライブラリは標準組み込みではないため、using ディレクティブを使用して明示的に読み込む。

```javascript
using DateTime;
```

### インスタンス化

インスタンス化は基本的には DateTime オブジェクトを new する方法で行う。

* `new DateTime()` ... 現在時刻でインスタンス化
* `new DateTime(dateString)` ... 文字列をパースしてインスタンス化
* `new DateTime(Unixtime)` ... UNIXエポックの時刻からインスタンス化
* `new DateTime(year, month, day[, hour, minute, second])` ... 日時情報を個別に指定してインスタンス化

ただし、以下でも可能（内部で new して返しているだけ）。好きなものを使ってください。

* `DateTime.parse(...)`
* `DateTime(...)`

尚、`dateString` は以下のような書式を解釈する。

* `"2020-01-01"`、`"2020-1-1"`
* `"2020/01/01"`、`"2020/1/1"`
* `"2020-01-01T10:00:05"`、`"2020-1-01T10:0:5"`
* `"2020/01/01 10:00:05"`、`"2020/1/01 10:0:5"`

### メソッド

DateTime オブジェクトには以下のメソッドがある。

|     メソッド      |                               動作概要                               |
| ----------------- | -------------------------------------------------------------------- |
| `isLeapYear()`    | うるう年であれば true を返す                                         |
| `unixtime()`      | 現在日時の Unix エポック時間を返す                                   |
| `datetime()`      | 現在日時を表すオブジェクトを返す                                     |
| `year()`          | 現在日時の「年」                                                     |
| `month()`         | 現在日時の「月」                                                     |
| `day()`           | 現在日時の「日」                                                     |
| `hour()`          | 現在日時の「時」                                                     |
| `minute()`        | 現在日時の「分」                                                     |
| `second()`        | 現在日時の「秒」                                                     |
| `weekday()`       | 現在日時の「週」（0: 日曜, 1: 月曜, ..., 6: 土曜）                   |
| `isSunday()`      | 日曜日であれば true を返す                                           |
| `isMonday()`      | 月曜日であれば true を返す                                           |
| `isTuesday()`     | 火曜日であれば true を返す                                           |
| `isWednesday()`   | 水曜日であれば true を返す                                           |
| `isThursday()`    | 木曜日であれば true を返す                                           |
| `isFriday()`      | 金曜日であれば true を返す                                           |
| `isSaturday()`    | 土曜日であれば true を返す                                           |
| `clone()`         | 日時オブジェクトのコピーを返す                                       |
| `addDay(day)`     | 日時オブジェクトを `day` 日進める（破壊的）                          |
| `subDay(day)`     | 日時オブジェクトを `day` 日戻す（破壊的）                            |
| `addMonth(month)` | 日時オブジェクトを `month` か月進める（破壊的）                      |
| `subMonth(month)` | 日時オブジェクトを `month` か月戻す（破壊的）                        |
| `next()`          | 次の日を表す新たな日時オブジェクトを返す                             |
| `+(day)`          | `day` 日後を表す新たな日時オブジェクトを返す                         |
| `-(day)`          | `day` 日前を表す新たな日時オブジェクトを返す                         |
| `>>(month)`       | `month` か月後を表す新たな日時オブジェクトを返す                     |
| `<<(month)`       | `month` か月前を表す新たな日時オブジェクトを返す                     |
| `<=>(dt)`         | 0: 日時が同じ、-1: `dt` のほうが後の日時、1: `dt` のほうが以前の日時 |
| `format(fmtString)`| `fmtString` のフォーマットに従ってフォーマットする。サポートするフォーマットは以下の通り。<br/>`%YYYY%`:4桁の年、`%YY%`:2桁の年<br/>`%MM%`:2桁の月、`%M%`:月<br/>`%DD%`:2桁の日、`%D%`:日<br/>`%hh%`:2桁の時、`%h%`:時<br/>`%mm%`:2桁の分、`%m%`:分<br/>`%ss%`:2桁の秒、`%s%`:秒<br/>|

### 月末

`<<` や `>>` で月を移動した場合、対応する月に同じ日が存在しない時は代わりにその月の末日が使われる。

```javascript
using DateTime;
System.println(DateTime("2001-3-28") << 1);  // 2001/02/28 00:00:00
System.println(DateTime("2001-3-31") << 1);  // 2001/02/28 00:00:00
```

このことは以下のように、もしかすると予期しない振る舞いをするかもしれない（Ruby と一緒）。

```javascript
using DateTime;
System.println(DateTime("2001-1-31") >> 2);        // 2001/03/31 00:00:00
System.println(DateTime("2001-1-31") >> 1 >> 1);   // 2001/03/28 00:00:00
System.println(DateTime("2001-1-31") >> 1 >> -1);  // 2001/01/28 00:00:00
```

### Range

Range で使えるようにするには、`next` メソッドと `<=>` メソッドを定義しておけば良い。なので、DateTime オブジェクトは Range で使用できる。

```javascript
using DateTime;
(DateTime(2020,1,1)..DateTime(2020,1,10))
    .each(&(d) => System.println(d));
```

`..` なので最後の日が含まれる。`...` の場合は最後の日は含まれない。

```
2020/01/01 00:00:00
2020/01/02 00:00:00
2020/01/03 00:00:00
2020/01/04 00:00:00
2020/01/05 00:00:00
2020/01/06 00:00:00
2020/01/07 00:00:00
2020/01/08 00:00:00
2020/01/09 00:00:00
2020/01/10 00:00:00
```

Range で使えるので for-in でもそのままいける。

```javascript
using DateTime;
for (var d in DateTime(2020,1,1)...DateTime(2020,1,10)) {
    System.println(d);
}
```

最終日を含まないループ。

```
2020/01/01 00:00:00
2020/01/02 00:00:00
2020/01/03 00:00:00
2020/01/04 00:00:00
2020/01/05 00:00:00
2020/01/06 00:00:00
2020/01/07 00:00:00
2020/01/08 00:00:00
2020/01/09 00:00:00
```

## おわりに

作り始めてから約半年。色々できるようになってきましたねー。ライブラリを充実させて、何かしらのアプリを作れるようになることが次の目標ですかね。ニッチな用途でのアプリをサクッと作れる、とかできるとどこかに居場所ができるかもしれない。

ではまた次回。