Timex利用コードをコマンド化すると実行時エラーが出る

（この記事は [Elixir (その2)とPhoenix Advent Calendar 2016](http://qiita.com/advent-calendar/2016/elixir2_and_phoenix) 22日目の記事です）

今回は、Timexを使うコードを、escriptでコマンド化した際、実行時エラーが出るのを回避する方法を解説 :alarm_clock:

escriptでのコマンド化についても、軽く解説します

<font color="red">【2021/7/30追記】
この方法、下記最新ElixirおよびOTPバージョンでは使えないことを確認しました
escriptで日時周りを使いたい場合は、Timexの代わりにElixir標準モジュールのDateTimeやCalendar等をご利用ください</font>

```
Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Elixir 1.12.0 (compiled with Erlang/OTP 24)
```

# escriptでElixirコードをコマンド化

まず、メインモジュールにmain()関数を追加します

コンソールから呼び出したときは、この関数が呼ばれます

```elixir:lib/sample.ex
defmodule Sample do
	def main( args \\ [] ) do
…
```

mix.exsの「def project」配下にescript利用を追記し、「def script」にメインモジュールのモジュール名を追加します（ここではElixirプロジェクト名を「sample」としています）

```elixir:mix.exs
defmodule Sample.MixProject do
  use Mix.Project

  def project do
    [
    …
      escript: escript(), 
      deps: deps()
    ]
  end

  def escript() do
    [ main_module: Sample ]
  end
…
```

escriptでコマンド化します

```
> mix escript.build
```

コンソールでの実行は、以下の通りです

```
> escript sample
```

Windows以外だと、以下でも実行できます

```
# chmod 755 ./sample
# ./sample
```

# Timex利用コードのコマンド化で実行時エラーが出る

Timexmモジュールを導入します

```elixir:mix.exs
defmodule Sample.Mixfile do
　…
  defp deps do
　…
    { :timex, "~> 3.0" }, 
　…
```

```
# mix deps.get
```

コマンド化して実行すると、以下エラーが出ます

```
# mix escript.build
# escript sample
Could not start application tzdata: exited in: Tzdata.App.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (MatchError) no match of right hand side value: {:error, {:shutdown, {:failed_to_start_child, Tzdata.EtsHolder, {%ArgumentError{message: "unknown application: :tzdata"}, [{Application, :app_dir, 1, [file: 'lib/application.ex', line: 428]}, 
           {Application, :app_dir, 2, [file: 'lib/application.ex', line: 437]}, {Tzdata.EtsHolder, :release_dir, 0, [file: 'lib/tzdata/ets_holder.ex', line: 86]}, {Tzdata.EtsHolder, :make_sure_a_release_dir_exists, 0, [file: 'lib/tzdata/ets_holder.ex', line: 70]}, 
           {Tzdata.EtsHolder, :make_sure_a_release_is_on_file, 0, [file: 'lib/tzdata/ets_holder.ex', line: 64]}, {Tzdata.EtsHolder, :init, 1, [file: 'lib/tzdata/ets_holder.ex', line: 10]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]},
           {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}}}
            (tzdata) lib/tzdata/tzdata_app.ex:15: Tzdata.App.start/2
            (kernel) application_master.erl:273: :application_master.start_it_old/4
```

これを回避するには、tzdataモジュールのバージョンを固定で指定します（元ネタは[こちら](https://github.com/bitwalker/timex/issues/86)）

```elixir:mix.exs
defmodule Sample.Mixfile do
　…
  defp deps do
　…
    { :tzdata, "== 0.1.8", override: true }, 
　…
```

ビルドし直して、実行すると、エラーが出なくなります :grinning:

```
# mix deps.get
# mix escript.build
# escript sample
```

p.s.OptionParseやコマンド終了ステータス等については、[「Elixirでいい感じのCLIをパッと作ってサッと共有(できるようになる。そう、Elixir 1.3ならね)」](http://qiita.com/ymtszw/items/2338bd32980345c4a417)が参考になります :art:

---

# p.s.

6/17（土）の[「第３回　☆ データサイエンスＬＴ＆勉強会 ☆ in LINE福岡！」](https://datascience.connpass.com/event/56428/)、60名を超える規模で盛り上がりました :angel_tone2:

[![image.png](https://qiita-image-store.s3.amazonaws.com/0/155423/dc8e01eb-8a63-3950-7de1-b83a88be9251.png)](https://datascience.connpass.com/event/56428/)

---

7/28（金）、[「Fukuoka CTO meetup」](https://connpass.com/event/59592/)という福岡のCTOが集まってディスカッションするイベントで講演することになりました :airplane_small:

技術チームのマネジメントや、技術選定の基準となる考え方、地方でCTOとして働く理由、どのようにCTOになったのか等について、アレコレお話すると思います

[![image.png](https://connpass-tokyo.s3.amazonaws.com/thumbs/19/49/19492217cdc53a29ea385cd17fd8aa4e.png)](https://connpass.com/event/59592/)