Day.js を使って誕生日から今何歳かを計算したい

# やりたいこと
Day.js を使って誕生日から年齢を計算したい。

---

# 正攻法
```js
const birthday = {
  year: 1995,
  month: 12,
  date: 6,
};

const today = dayjs();
const { year, month, date } = birthday;
const dayjsBirthday = dayjs(`${year}-${month}-${date}`);

console.log(today.diff(dayjsBirthday, 'year'));
```

---

# ![NHK (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114828/9fe78102-96a7-944f-13a7-9f36fc290a5d.png)

---

# 他の方法はないか :thinking: 

---

# Day.js の `RelativeTime` プラグインを使えないか :bulb: 

---

## `RelativeTime` プラグインとは
```js
import relativeTime from "dayjs/plugin/relativeTime"
dayjs.extend(relativeTime)

dayjs('1999-01-01').fromNow() // 20 years ago
```

---

# 主な用途

![glicoさん___glico800____Twitter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114828/adfe6de3-ce10-acf9-0e9d-fc57b608564c.png)


---

## デフォルトのしきい値だと2年未満が曖昧
| Range                    | Key | Sample Output                    |
|--------------------------|-----|----------------------------------|
| 0 to 44 seconds          | s   | a few seconds ago                |
| 45 to 89 seconds         | m   | a minute ago                     |
| 90 seconds to 44 minutes | mm  | 2 minutes ago ... 44 minutes ago |
| 45 to 89 minutes         | h   | an hour ago                      |
| 90 minutes to 21 hours   | hh  | 2 hours ago ... 21 hours ago     |
| 22 to 35 hours           | d   | a day ago                        |
| 36 hours to 25 days      | dd  | 2 days ago ... 25 days ago       |
| 26 to 45 days            | M   | a month ago                      |
| 46 days to 10 months     | MM  | 2 months ago ... 10 months ago   |
| 11 months to 17months    | y   | a year ago                       |
| 18 months+               | yy  | 2 years ago ... 20 years ago     |

---

## しきい値はカスマイズできる
extend 時にしきい値を `thresholds` という名前で渡してあげる。
（ `updateLocale` を使っても渡せるらしい。今回は未検証。）

```js
import relativeTime from "dayjs/plugin/relativeTime"

// strict thresholds
const thresholds = [
  { l: 's', r: 1 },
  { l: 'm', r: 1 },
  { l: 'mm', r: 59, d: 'minute' },
  { l: 'h', r: 1 },
  { l: 'hh', r: 23, d: 'hour' },
  { l: 'd', r: 1 },
  { l: 'dd', r: 29, d: 'day' },
  { l: 'M', r: 1 },
  { l: 'MM', r: 11, d: 'month' },
  { l: 'y' },
  { l: 'yy', d: 'year' },
];
dayjs.extend(relativeTime, {
  thresholds,
});
```

---

## `thresholds` の書き方がドキュメントに載っていない問題

---

## コードから読み解く
[この辺を読む](https://github.com/iamkun/dayjs/blob/f2e479006a9a49bc0917f8620101d40ac645f7f2/src/plugin/relativeTime/index.js#L43-L64)

- l: key label （しきい値のキーとなるラベル、新しいキーを追加したりできる）
- r: range （しきい値、最後の要素では定義不要）
- d: unit of diff （`diff` メソッドで計算する際の単位、単位が変わるときだけ定義）

```js
// default threasholds
[
  { l: 's', r: 44, d: 'second' },
  { l: 'm', r: 89 },
  { l: 'mm', r: 44, d: 'minute' },
  { l: 'h', r: 89 },
  { l: 'hh', r: 21, d: 'hour' },
  { l: 'd', r: 35 },
  { l: 'dd', r: 25, d: 'day' },
  { l: 'M', r: 45 },
  { l: 'MM', r: 10, d: 'month' }, // 46 days to 10 months
  { l: 'y', r: 17 }, // 11 months to 17 months
  { l: 'yy', d: 'year' } // 18 months+
]
```

---

## 誕生日を計算してみる

```js
import relativeTime from "dayjs/plugin/relativeTime"

const thresholds = [
  { l: 's', r: 44, d: 'second' },
  { l: 'm', r: 89 },
  { l: 'mm', r: 44, d: 'minute' },
  { l: 'h', r: 89 },
  { l: 'hh', r: 21, d: 'hour' },
  { l: 'd', r: 35 },
  { l: 'dd', r: 25, d: 'day' },
  { l: 'M', r: 45 },
  { l: 'MM', r: 11, d: 'month' }, // 46 days to 11 months
  { l: 'y', r: 23 }, // 12 months to 23 months
  { l: 'yy', d: 'year' } // 24 months+
]
const rounding = Math.floor; // default is Math.round

dayjs.extend(relativeTime, {
  thresholds,
  rounding,
});

// input data
const birthday = {
  year: 1995,
  month: 12,
  date: 6,
};

const { year, month, date } = birthday;
const dayjsBirthday = dayjs(`${year}-${month}-${date}`);

console.log(dayjsBirthday.fromNow());
```

CodePen: https://codepen.io/ezawa800/pen/PoKrmGa

---

# 結論： この用途では実用性はない
Day.js の `RelativeTime` プラグインを理解するのには良さそうなサンプルだが、実際に正確に年齢計算するなら `diff` メソッドでよい。

---

# 参考
Day.jsで相対日時を厳密に表示する（thresholds） - Zenn
https://zenn.dev/catnose99/articles/ba540f5c233847

---

# Thank you