こんにちは
エラーが出た背景
rooを使ってexcelの日時のデータを取り込むよう開発を進めました。
ある程度できあがって確認しようとすると、下記のようなエラーが出ました。
おそらく, in_time_zone
メソッドがinteger型に対応できていないと
下記に
- エラーメッセージが出た部分
- 対応するメソッド(controller)
- エラーが発生したファイル
を載せています。
def time_from_excel_date_time(excel_date, excel_time) date = excel_date.in_time_zone if excel_time.is_a?(String) time = excel_time.to_time hour = time.hour minute = time.min elsif excel_time.is_a?(Integer) hour = (excel_time / 3600) minute = (excel_time % 3600 / 60) end date + hour.hour + minute.minute end
普段取り込むexcelファイル(該当箇所のみ)
id | 日付 | 開始時間 |
---|---|---|
12/9 | 1:00 | |
12/8 | 1:00 | |
11/27 | 1:00 | |
11/26 | 1:00 |
今回エラーが発生したexcelファイル(該当箇所のみ)
id | 日付 | 開始時間 |
---|---|---|
12月9日 | 1:00 | |
12月8日 | 1:00 | |
11月27日 | 1:00 | |
11月26日 | 1:00 |
原因
上の部分を見ていただければわかる通り、日付
の区切られている部分が/
か月日
かの違いによるものでした。
この部分が違うと、
/
だとそのまま(String型)、
月日
だと数字(Integer型)
が変数として取り込まれるので、String型にしか対応していなかったメソッドでエラーが発生してしまいました。
改善策
そのためcontrollerを書き換えました。
def time_from_excel_date_time(excel_date, excel_time) EXCEL_EPOCH = 2209078800 TICKS_PER_DAY = 60 * 60 * 24 if excel_date.is_a?(String) || excel_date.is_a?(Date) date = excel_date.in_time_zone elsif excel_date.is_a?(Integer) # 日付が漢字の場合、integer型で受け取る => 1899/12/31 からどれくらいの日数がたったかを表している # Unixのゼロタイム(基準)が "1970/1/1" に設定されている為、下記ステップで日付を求める # 1. TICKS_PER_DAY をかけて、1899/12/31 からどれくらいの秒数がたったかを計算 # 2. 1から EXCEL_EPOCH 秒をを引き、1970/1/1 からどれくらいの秒数がたったかを計算 unix_timestamp = excel_date * TICKS_PER_DAY - EXCEL_EPOCH date = Time.at(unix_timestamp).to_datetime - 8.hours - 1.day end if excel_time.is_a?(String) time = excel_time.to_time hour = time.hour minute = time.min elsif excel_time.is_a?(Integer) hour = (excel_time / 3600) minute = (excel_time % 3600 / 60) end date + hour.hour + minute.minute end
excelから取り込んだ日付の変数が入っているexcel_date
に対して、if文でString型とInteger型に分けて処理を走らせることにしました。
また、unix_timestamp
の部分が複雑なので下記に説明をしたいと思います。
unixとexcel
このコントローラーの記述は主にunixとexcelの基準の時間を合わせるために書きました。
コメントアウトでも書いてありますが、
excelは基準が1899/12/31
なので帰ってくる変数は、1899/12/31から何日たっているか
を表します。
しかし、Rubyに限らずunixを基準としているプログラミング言語は1970/1/1(ゼロタイム)
を基準に作動します。
なので、excelの変数をunixの基準に合わせるために
unix_timestamp = excel_date * TICKS_PER_DAY - EXCEL_EPOCH
の記述をしています。
最後に
今回僕の初めての投稿なので至らない点があると思いますが、
僕なりに一生懸命頑張ったつもりです。笑
もし、何かアドバイスなどありましたらぜひ教えていただきたいです!