はじめに/問題発生時の状況
開発環境
Ruby 2.6.5
Rails 6.0.3.4
MySQL
Visual Studio Code
(GoogleChrome)
カレンダーアプリ的なものを作成中です。
日付と開始・終了時間をそれぞれ分けてDBへ保存したいので、時間についてはtime型カラムで、time_select
を使用してフォームを作成しました。
<div class="start-date-input">
<div class="form-title">
開始時間
<span class="indispensable">必須</span>
</div>
<div class='input-date-wrap'>
<%= f.time_select(:start_time, {class:'select-date', id:"start-time", prompt:'--', time_separator: ':'}, ignore_data: true) %>
</div>
</div>
<div class="finish-date-input">
<div class="form-title">
終了時間
<span class="indispensable">必須</span>
</div>
<div class='input-date-wrap'>
<%= f.time_select(:start_time, {class:'select-date', id:"start-time", prompt:'--', time_separator: ':'}, ignore_data: true) %>
</div>
</div>
上記のように日付と時間をそれぞれフォームへ入力して、試しにデータを送信すると、
日時・各時間共にそれぞれ無事にDBへ保存されている様子です。
ではビューへ表示しようと取得すると…
<div class="event-show-info-left">
<p><%= @event.day %></p>
<p><strong><%= @event.start_time %></strong></p>
<p><strong>↓</strong></p>
<p><strong><%= @event.finish_time %></strong></p>
</div>
!!!?!!!?
時間にそれぞれ、謎の年月も一緒に表示されております…
20世紀なこの子は一体何者…
原因の考察・検証
一度、送信データのparamsを確認しました。
[1] pry(#<EventsController>)> params
=> <ActionController::Parameters {
(省略)
"day(1i)"=>"2020", "day(2i)"=>"12", "day(3i)"=>"2",
"start_time(1i)"=>"1", "start_time(2i)"=>"1", "start_time(3i)"=>"1", "start_time(4i)"=>"10", "start_time(5i)"=>"00",
"finish_time(1i)"=>"1", "finish_time(2i)"=>"1", "finish_time(3i)"=>"1", "finish_time(4i)"=>"13", "finish_time(5i)"=>"30",
(省略)
} permitted: false>
(1i)…年
(2i)…月
(3i)…日
(4i)…時
(5i)…分
というように、各時間と共に年月日も付与されていることが分かります。
時間を保存するのでtime型にしたので、DBには反映されませんが、
time_select
の仕様としては年月日に"1"もつけて扱われる、というように考えられます。
この"1"というのがそのままビューに取得され、例の2000-01-01
の原因なようです。
〜では、時間だけを取得するにはどうするか…?〜
ビュー側に何か一工夫したいところです。
調べたところ…
【公式】Ruby 2.7.0 リファレンスマニュアル instance method Time#strftime
strftime(format) -> String
時刻を format 文字列に従って文字列に変換した結果を返します。
上記を参考に、strftime
が活躍しそうです!
開始時間・終了時間クラスに対してstrftime
を使用し、文字列にフォーマットします。
結果
時間のみを取得するので、フォーマットは下記を使います。
- %H: 24時間制の時(00-23)
- %M: 分(00-59)
先ほどのビューファイルに、.strftime("%H:%M")
を付け加えました。
<div class="event-show-info-left">
<p><%= @event.day %></p>
<p><strong><%= @event.start_time.strftime( "%H:%M" ) %></strong></p>
<p><strong>↓</strong></p>
<p><strong><%= @event.finish_time.strftime( "%H:%M" ) %></strong></p>
</div>
時間のみ表示が出来ました!!
終わりに/感想
strftime
とtime_select
は名コンビでした!
時間の扱いについては今後、規模の大きな実装をするようになると
タイムゾーンや閏年などの特殊な配慮が必要になってくるとも感じました。
これを機に、Timeクラス系クラスの理解も深めたいと思います。
初学者で拙い記事ですが、少しでもお役に立てると嬉しく思います。
最後まで読んでいただき、誠にありがとうございました。
追記
11/11 21:40
日時のフォーマットについてはDRYの面から、タイムゾーンとロケール設定、l
メソッドで対応するのが良いとご指導いただきました。
下記の記事をご参照ください。
【初心者向け・動画付き】Railsで日時をフォーマットするときはstrftimeよりも、lメソッドを使おう
@jnchito 様 ありがとうございました!
参考記事
【公式】Ruby 2.7.0 リファレンスマニュアル instance method Time#strftime
【公式】Ruby on Rails 6.0.3.4 Module ActionView::Helpers::DateHelper