LoginSignup
11
5

More than 3 years have passed since last update.

Time型データから時刻のみを取得したい…!【strftime】※追記あり

Last updated at Posted at 2020-11-11

はじめに/問題発生時の状況

開発環境

Ruby 2.6.5
Rails 6.0.3.4
MySQL
Visual Studio Code
(GoogleChrome)

カレンダーアプリ的なものを作成中です。
日付と開始・終了時間をそれぞれ分けてDBへ保存したいので、時間についてはtime型カラムで、time_selectを使用してフォームを作成しました。

new.html.erb(時間フォーム分のみ抜粋)
<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>

form

上記のように日付と時間をそれぞれフォームへ入力して、試しにデータを送信すると、

db

日時・各時間共にそれぞれ無事にDBへ保存されている様子です。
ではビューへ表示しようと取得すると…

show.html.erb
<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>

before

!!!?!!!?

時間にそれぞれ、謎の年月も一緒に表示されております…
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")を付け加えました。

show.html.erb(修正)
<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>

after

時間のみ表示が出来ました!!

終わりに/感想

strftimetime_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

【Qiita】strftimeとは?

【Qiita】Time型のデータの値を、時刻部分だけ表示する

【Hatena Blog】time_selectで時間だけを入力させる[rails]

11
5
2

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
11
5