Emacs で時の流れを感じる

# なにをやったの

ふらっと外に出てみたらちょうど空が夕焼けていて「ずいぶん日が短くなってきたなあ」とか、あるいは夜、なんとなく空を見上げてみたら綺麗な満月で「もうひと月たったか」とか、そんな、ふと時の流れを感じる瞬間が僕は好きです。

が、社会人になってから、退社したら外はもう夜、という日がほとんどになって、そんな瞬間を感じることが減ってしまったなあとふと思いました。

そんなわけで、その時刻の空の色（イメージ）、月齢、天気を反映した時計ウィジェットを作ってみました。モードラインなどに置いておくと、ふと目をやったときに、ちょっとほっこりできるかもしれません。

# スクリーンショット

モードラインに設置

![スクリーンショット 2018-01-18 14.46.14.png](https://qiita-image-store.s3.amazonaws.com/0/54240/ac398247-a9db-1696-b061-e0f3a77c393f.png)

色のサンプル

<img width="55" alt="screenshot_colors.png" src="https://qiita-image-store.s3.amazonaws.com/0/54240/b9f41328-b90b-42c7-2fc0-1463f865bbc8.png">

# インストール

GitHub: https://github.com/zk-phi/sky-color-clock

load-path の通ったディレクトリにダウンロード (clone)、 `init.el` からロードして、緯度を設定してください。

```lisp
(require 'sky-color-clock)      ; パッケージをロード
(sky-color-clock-initialize 35) ; 東京（例）の緯度で初期化
```

天気を反映したい場合は、 openweathermap の API key を取得して、 `sky-color-clock-initialize-openweathermap-client` で設定します。

```lisp
(sky-color-clock-initialize-openweathermap-client "API-key" 1850144) ; 東京の City ID
```

`sky-color-clock` 関数がいい感じに装飾された文字列を返してくれるので、例えばモードラインに表示したい場合は

```lisp
;; デフォルトの mode-line-format の先頭に sky-color-clock を追加
(push '(:eval (sky-color-clock)) (default-value 'mode-line-format))
```

のように、 `mode-line-format` の中で `sky-color-clock` を呼び出すように設定してやれば ok です (詳しくは `mode-line-format` のドキュメントを見てください)。

# 時刻のフォーマット

`sky-color-clock-format` で設定できます。中で `format-time-string` を呼んでいるので、 `format-time-string` が解釈できるようなフォーマット文字列を設定してあげてください。

```lisp
(setq sky-color-clock-format "%d %H:%M")
```

文字を表示しないようにして、空の色だけでざっくりした時間だけを感じとる、ストイックな時計として使うとかもできますね。

```lisp
(setq sky-color-clock-format "")
```

# 月齢

「月齢計算」とかで調べるといろいろ難しい言葉が出てくるのですが、英語 wiki にそれっぽい項目がありました。

https://en.wikipedia.org/wiki/Lunar_month

要約すると、「月の公転周期は 27.32 日だけど、満ち欠けは太陽・地球・月の位置関係で決まるからそれよりちょっと長くて、 29.53 日くらいになるよ。ただし時期によってちょっと変わるよ」ということみたいです。

精度はいらないので、適当な新月の時刻からの時間を計算して、周期で mod 取った値から、一番近い絵文字を選んでいます。

`sky-color-clock-enable-emoji-icon` でトグルできます。

```lisp
(setq sky-color-clock-enable-emoji-icon t)
```

----

実装してから、 lunar.el というもっと高精度な月齢計算が組み込みで入っているのに気づきましたが、こちらのほうがずっと軽量だからモードラインにはちょうどいいのだと思うことにしました。悔しくないです。

# 日の出・日の入り

日の出日の入りを緯度から計算して、その時刻に合った空の色を表示します。

日の出・日の入りの時刻もまじめに計算すると難しいっぽい (太陽の位置の計算だけで本が書けるらしい？) ですが、やっぱり英語 wiki に手頃な近似が載っていたのでこれを使うことにしました。

https://en.wikipedia.org/wiki/Sunrise_equation

両辺 `arccos` 取ると、

    <日没の hour angle> = arccos(-tan(<緯度>) * tan(<太陽の赤緯>))

となって、日没の hour angle (時刻を 0 時～ 24 時の代わりに -180°～ +180° で表したもの) が緯度と太陽赤緯から求まります。ここから時刻を逆算できます。

太陽赤緯は季節によって変わって、これも英語 wiki

https://en.wikipedia.org/wiki/Position_of_the_Sun

の「Calculations」の節にいい感じの近似式が載っているので、そのまま使いました (`arcsin(sin(x)*cos(y))` はだいたい `x*cos(y)` だね！とか、計算のヒントまで書かれていて親切です)。

    <太陽赤緯> = -23.44° * cos(360 / 365 * (<年が明けてからの日数> + 10))

月齢よりは重い計算になるので、起動時に一度計算してキャッシュします。一年を通して Emacs を kill しない人は定期的に `(sky-color-clock-initialize <緯度>)` してください（一生冬のままになります）。

空の色は、いくつかキーになる色を選んで、その間を線形に補完する感じでグラデーションにしました。こんな

http://i0.kym-cdn.com/photos/images/original/000/511/922/ea9.jpg

エモみのある画像を見つけたので、これをペイントで 1px x 24px につぶして 24 色スポイトしたものを叩き台にしました。そのままだと中間色が綺麗に出なかったりしたので、いつ見ても気持ちいい色が出るようにちょこちょこ調整しています。あとマジックアワー (日没直後の、空が紫がかる数十分) を足しました。尊い。

----

日の出日の入りも組み込みの solar.el でもっと高精度に計算できるのを後で発見してしまいましたが、勉強になったので悔しくないです（悔しい）。

# 天気

Openweathermap の API key を設定すると、

```lisp
(sky-color-clock-initialize-openweathermap-client "API-key" 1850144)
```

30 分ごとに API を叩いて、

- 曇り度合い
- 温度
- 雨 or 雪

の情報を取得します。

## 曇り度合い

外が明らかに曇りなのに時計の背景は綺麗な青だったときにイラっとしたので実装しました。

曇り度合いを空の色に反映します。

<img width="567" alt="screenshot_cloudiness.png" src="https://qiita-image-store.s3.amazonaws.com/0/54240/872d08f3-e3c8-9f4d-2caf-e53dbeb39258.png">

すごく曇っている日は、空の色も彩度が落ちて、明るさの変化もボンヤリします。

## 温度 / 雨・雪

昼休みなど外に出るときに、「どれくらい厚着してったほうがいいかな」とか「傘いるかな」とかわかると便利だなと思って実装しました。

`sky-color-clock-enable-temperature-indicator` でトグルできます。

```lisp
(setq sky-color-clock-enable-temperature-indicator t)
```

雨・雪が降っている場合は月齢アイコンが雨・雪アイコンに変わります。

<img width="749" alt="screenshot_rainy.png" src="https://qiita-image-store.s3.amazonaws.com/0/54240/95fb0e9e-cd3b-2eff-1b3a-379d571d8ad2.png">

温度は時刻の右に色で表示します。15 ℃を無色として、それより寒ければ寒色寄り、それより暑ければ暖色寄りになります。

<img width="466" alt="スクリーンショット 2018-01-17 18.15.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/54240/48c0404f-f6fd-4ec0-3e3f-20d5c492d1ba.png">

(左端が 0 ℃、中央が 15 ℃ 右端が 30 ℃)

# まとめ

一緒に時を流れを感じましょう。