6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

駆け出しエンジニア日記Advent Calendar 2020

Day 21

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

Last updated at Posted at 2021-02-26

はじめに

  • Elixir楽しんでいますか:bangbang::bangbang::bangbang:
  • AndroidでSuicaの履歴をみるというものを作ってみました
  • 「先頭から7bitが年、4ビットが月、残り5ビットが日」、「とある2バイトが残高、ただしリトルエンディアン」こういった処理って地味にけっこうたいへんではないでしょうか
  • Elixirならパターンマッチですっきり書けますのでご紹介します
  • 2021/2/27に開催するautoracex #12というもくもく会の成果とします

Screenshot_20210226-200730.png

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

参考にしたサイト

スクリーンショット 2021-02-26 15.49.26.png

( Felica Library > Wiki > Suica )

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

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日が簡単に取り出せることを示します
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とか4bit5bitを指定することでパターンマッチで値をとれます
  • シフトなどの演算を自分で書く必要はありません

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

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

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という文法さえ覚えてしまえばパターンマッチ一発で値を取得できます

Wrapping Up :lgtm::lgtm::lgtm::lgtm::lgtm:

  • 他にどういった指定が可能なのかについては、公式にある<<>> の説明をご参照ください
  • ビット数を指定して、パターンマッチができるのいいですよね:bangbang::bangbang::bangbang:
  • Enjoy Elixir :rocket::rocket::rocket:

(最後の最後に)Elixirってなによ? という方へ

image.png

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?