先頭から7bitが年、4ビットが月、残り5ビットが日 (Elixir)

# はじめに
- [Elixir](https://elixir-lang.org/)楽しんでいますか:bangbang::bangbang::bangbang:
- [Android](https://developer.android.com/?hl=ja)でSuicaの履歴をみるというものを作ってみました
- 「先頭から7bitが年、4ビットが月、残り5ビットが日」、「とある2バイトが残高、ただしリトルエンディアン」こういった処理って地味にけっこうたいへんではないでしょうか
- [Elixir](https://elixir-lang.org/)ならパターンマッチですっきり書けますのでご紹介します
- 2021/2/27に開催する[autoracex #12](https://autoracex.connpass.com/event/205985/)というもくもく会の成果とします

![Screenshot_20210226-200730.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/25a822d6-f709-a55e-29d8-26a24b5cdbb5.png)

- 以下で紹介するサイトの記事を参考にするとすぐにできました :pray::pray_tone1::pray_tone2::pray_tone3::pray_tone4::pray_tone5:


## 参考にしたサイト
- [AndroidアプリでNFCタグを読み書きするための基礎知識](https://www.atmarkit.co.jp/ait/articles/1211/27/news072.html)
- [AndroidのNFCでSuicaの履歴を読んでみる](https://qiita.com/kurotsu/items/f351815ec6a65294ce0f)
    - 履歴を読み出すためのコマンドと取得例
- https://github.com/thinkAmi/RubotoFelicaRead/blob/acccaa6f2a513154d25b7583061ac3e517be6c68/src/net/kazzz/felica/suica/Suica.java
    - 「[AndroidのNFCでSuicaの履歴を読んでみる](https://qiita.com/kurotsu/items/f351815ec6a65294ce0f)」記事で省略されている処理の実装の参考になりそうなものが書いてあります
- [Felica Library > Wiki > Suica](https://ja.osdn.net/projects/felicalib/wiki/suica)
    - 履歴を読み出すためのコマンドを実行したあとに返ってくる値の仕様(構造)を有志の方がまとめてくださっています :pray::pray_tone1::pray_tone2::pray_tone3::pray_tone4::pray_tone5:

![スクリーンショット 2021-02-26 15.49.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/aa1e211c-efd0-2685-50e8-889807b6aa81.png)

( [Felica Library > Wiki > Suica](https://ja.osdn.net/projects/felicalib/wiki/suica) )




# 先頭から7bitが年、4ビットが月、残り5ビットが日


## Java

```Java:
	public Date getProccessDate(int date, int time) {
		int yy = date >> 9;
		int mm = (date >> 5) & 0xf;
		int dd = date & 0x1f;
		Calendar c = Calendar.getInstance();
		c.set(Calendar.YEAR, 2000 + yy);
		c.set(Calendar.MONTH, mm-1);
		c.set(Calendar.DAY_OF_MONTH, dd);

		int hh = time >> 11;
		int min = (time >> 5) & 0x3f;
		c.set(Calendar.HOUR_OF_DAY, hh);
		c.set(Calendar.MINUTE, min);
		return c.getTime();
	}
```

## Elixir

- `"FgEAAilfAlyLByQDAAWHMA=="`は冒頭の写真でみせました表示例の最初のデータをBase64エンコードしたものであります
- これを例に2020年10月31日が簡単に取り出せることを示します

```elixir
iex> Base.decode64 "FgEAAilfAlyLByQDAAWHMA=="
{:ok, <<22, 1, 0, 2, 41, 95, 2, 92, 139, 7, 36, 3, 0, 5, 135, 48>>}
iex> <<_::32, year::7, month::4, day::5, _::binary>> = <<22, 1, 0, 2, 41, 95, 2, 92, 139, 7, 36, 3, 0, 5, 135, 48>>
<<22, 1, 0, 2, 41, 95, 2, 92, 139, 7, 36, 3, 0, 5, 135, 48>>
iex> year
20
iex> month
10
iex> day
31
```
- どうでしょうか、細かい書き方は抜きにして`7bit`とか`4bit`、`5bit`を指定することでパターンマッチで値をとれます
- シフトなどの演算を自分で書く必要はありません


# とある2バイトが残高、ただしリトルエンディアン

## Java

```java:
remain = Long.valueOf((bytesToInt(new byte[]{response[24], response[23]})));

...
	private int bytesToInt(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(String.format("%02X", b));
		}
		return Integer.valueOf(sb.toString(), 16);
	}


```

- こちらも冒頭の写真の最初のデータの残高804円が取り出せる様子を示します

## Elixir

```elixir:
iex> <<_::80, remain::16-little, _::binary>> = <<22, 1, 0, 2, 41, 95, 2, 92, 139, 7, 36, 3, 0, 5, 135, 48>>  
<<22, 1, 0, 2, 41, 95, 2, 92, 139, 7, 36, 3, 0, 5, 135, 48>>
iex> remain
804
```
- どうでしょうか、こちらも`16-little`という文法さえ覚えてしまえば[パターンマッチ](https://elixir-lang.org/getting-started/pattern-matching.html)一発で値を取得できます

# Wrapping Up :lgtm::lgtm::lgtm::lgtm::lgtm:
- 他にどういった指定が可能なのかについては、公式にある[<<>>](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#%3C%3C%3E%3E/1) の説明をご参照ください
- ビット数を指定して、[パターンマッチ](https://elixir-lang.org/getting-started/pattern-matching.html)ができるのいいですよね:bangbang::bangbang::bangbang:
- Enjoy [Elixir](https://elixir-lang.org/) :rocket::rocket::rocket: 

# (最後の最後に)[Elixir](https://elixir-lang.org/)ってなによ？ という方へ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/601aeb87-9d1d-6a9d-b30b-338507dc593e.png)

- :point_up::point_up_tone1::point_up_tone2::point_up_tone3::point_up_tone4::point_up_tone5: 2020/12/26時点くらいのスクリーンショット
- [Elixir](https://elixir-lang.org/)についてもっと知りたい方は下記の本:books:をオススメします
    - [プログラミングElixir（第2版）](https://www.ohmsha.co.jp/book/9784274226373/)
    - [Elixir実践ガイド](https://book.impress.co.jp/books/1120101021)
- [elixir.jp Slack](https://join.slack.com/t/elixirjp/shared_invite/zt-ae8m5bad-WW69GH1w4iuafm1tKNgd~w)の`#autoracex`というところに私は入り浸っておりますのでお気軽にお声がけください
- [勉強会が頻繁に行われています](https://twitter.com/piacere_ex/status/1364109880362115078)
    - [autoracex](https://autoracex.connpass.com/) 【毎週月曜】
    - [Sapporo.beam](https://sapporo-beam.connpass.com)　　【毎週水曜】
    - [OkazaKirin.beam](https://okazakirin-beam.connpass.com)　【毎週木曜】
    - [fukuoka.ex／kokura.ex](https://fukuokaex.connpass.com)　【毎月2～3回】
    - [NervesJP](https://nerves-jp.connpass.com/) 　【毎月1回】