【概要】
最近、ライブラリを読むのが楽しくて、今まで敬遠していた Rails のソースコードを読み始めたので、記録していく。全部のメソッドは書いてないよ。
- 環境
- Ruby 2.7.0
- Rails 6.0.2
- 参考: 学習情報 URL
※ 例文の実行環境は既存のRailsプロジェクト
bash
gem install timecop
rails c
# `rails c`起動後, timecop を読み込む( ディレクトリは,`gem which timecop`で検索 )
require "/usr/local/bundle/gems/timecop-0.9.1/lib/timecop.rb"
# zone を指定
Time.zone = "Asia/Tokyo"
=> "Asia/Tokyo"
# 本記事における現在時刻を`2020年3月1日12:00`に固定
time_for_freeze = Time.local(2020, 3, 1, 12)
Timecop.freeze time_for_freeze
【本文】
□ Time Class と Date Class 拡張
time = Time.now
=> 2020-03-01 12:00:00 +0900
time.class
=> Time
after_time = time.in_time_zone
=> Sun, 01 Mar 2020 12:00:00 JST +09:00
after_time.class
=> ActiveSupport::TimeWithZone
# 引数で他都市の TimeZone を指定可能
after_time = time.in_time_zone("London")
=> Sun, 01 Mar 2020 03:00:00 GMT +00:00
- ↑ Time と Date インスタンスを TimeWithZone クラスに変換する。
□ Time Class 拡張
Time.zone
=> #<ActiveSupport::TimeZone:0x0000563071f03910
@name="Asia/Tokyo",
@tzinfo=#<TZInfo::DataTimezone: Asia/Tokyo>,
@utc_offset=nil>
- ↑ 設定された zone を元に TimeZone インスタンスを生成する。
Time.zone = "Sapporo"
=> "Sapporo"
Time.zone
=> #<ActiveSupport::TimeZone:0x0000563071fd3958
@name="Sapporo",
@tzinfo=#<TZInfo::DataTimezone: Asia/Tokyo>,
@utc_offset=nil>
- ↑ 設定可能な TimeZone に変更する。
Time.use_zone("London") do
Time.zone.now
end
=> Sun, 01 Mar 2020 03:00:00 GMT +00:00
- ↑ ブロック内で指定した TimeZone による処理が可能となる。
- ↑ 処理後は、元の TimeZone に戻る。
Time.find_zone!("London")
=> #<ActiveSupport::TimeZone:0x00005630705df1f0
@name="London",
@tzinfo=#<TZInfo::DataTimezone: Europe/London>,
@utc_offset=nil>
Time.find_zone("Naboo")
=> nil
- ↑ Rails 内の定数で定義された都市の TimeZone を表示する。
- ↑ 存在しなかったら例外起こすけど、
!
を外したら nil を返す。
□ TimeZone Class
■ Class Methods
ActiveSupport::TimeZone::MAPPING
=> {"International Date Line West"=>"Etc/GMT+12",
"Midway Island"=>"Pacific/Midway",
"American Samoa"=>"Pacific/Pago_Pago",
# 省略...
"Osaka"=> "Asia/Tokyo",
"Sapporo"=> "Asia/Tokyo",
"Tokyo"=> "Asia/Tokyo",
# 省略...
}
- ↑ Rails で定義可能な TimeZone を確認できる。
- ↑ 定数だが便宜上、ここに記載した( 他の Class Method 紹介してないや... )
■ Instance Methods
Time.zone =~ "Tokyo"
=> true
Time.zone =~ "Sapporo"
=> false
- ↑ 設定された都市を比較できる。
Time.zone.to_s
=> "(GMT+09:00) Tokyo"
- ↑ 現在の zone と utc のオフセット及び設定された都市を表示する。
Time.zone.local(2020, 1, 1, 11, 11, 11)
=> Wed, 01 Jan 2020 11:11:11 JST +09:00
Time.zone.local(2020)
=> Wed, 01 Jan 2020 00:00:00 JST +09:00
- ↑
Time.utc
を元に TimeWithZone に変換している。
f = Time.utc(2020, 3, 1, 12, 00, 00).to_f
=> 1583064000.0
Time.zone.at(f)
=> Sun, 01 Mar 2020 21:00:00 JST +09:00
# ナノ秒まで指定可能
Time.zone.at(f, 123456.789).nsec
=> 123456789
- ↑
Time.at
を元に TimeWithZone Class に変換する。
Time.zone.iso8601("2020-03-01T12:00:00+09:00")
=> Sun, 01 Mar 2020 12:00:00 JST +09:00
- ↑ ISO8601 形式の文字列を TimeWithZone Class に変換する。
- ↑
Time#iso8601
の TimeWithZone 版
Time.zone.rfc3339("2020-03-01T12:00:00.123456789+09:00")
=> Sun, 01 Mar 2020 12:00:00 JST +09:00
- ↑ RFC3339 形式の文字列を TimeWithZone Class に変換する。
- ↑
Time#rfc3339
の TimeWithZone 版
Time.zone.parse("20200202111111")
=> Sun, 02 Feb 2020 11:11:11 JST +09:00
Time.zone.parse("20200202")
=> Sun, 02 Feb 2020 00:00:00 JST +09:00
Time.zone.parse("2020-02-02 11:11:11")
=> Sun, 02 Feb 2020 11:11:11 JST +09:00
Time.zone.parse("2020-02-02")
=> Sun, 02 Feb 2020 00:00:00 JST +09:00
Time.zone.parse("2020-02")
=> ArgumentError: argument out of range
- ↑ 引数の文字列をDate._parseで変換するため、少なくとも月日が必要となる。
Time.zone.strptime("2020-03-01 11:11:11", "%Y-%m-%d %H:%M:%S")
=> Sun, 01 Mar 2020 11:11:11 JST +09:00
Time.zone.strptime("11:::11:::11", "%H:::%M:::%S")
=> Sun, 01 Mar 2020 11:11:11 JST +09:00
Time.zone.strptime("Mar.1 2020", "%b.%d %Y")
=> Sun, 01 Mar 2020 00:00:00 JST +09:00
- ↑ 第一引数に任意の文字列、第二引数にフォーマットを指定することで、フォーマットを元に文字列を TimeWithZone に変換する。
- ↑ 引数の文字列をDateTime._parseで変換している。
- ? メソッド名は String Parse Time の略 ?
Time.zone.today
=> Sun, 01 Mar 2020
Time.zone.tomorrow
=> Mon, 02 Mar 2020
Time.zone.yesterday
=> Sat, 29 Feb 2020
- ↑
Time.zone.tzinfo
を使用して、Date Class に変換する。
Time.zone.local_to_utc(Time.parse("2020-03-01 12:00"))
=> 2020-03-01 03:00:00 UTC
Time.zone.utc_to_local(Time.parse("2020-03-01 12:00"))
=> 2020-03-01 21:00:00 UTC
- ↑ UTC の Time Class に変換する。
# utc = Time.zone.local_to_utc(Time.parse("2020-03-01 12:00"))
Time.zone.period_for_utc(utc)
=> #<TZInfo::TimezonePeriod: #<TZInfo::TimezoneTransitionDefinition: #<TZInfo::TimeOrDateTime: -577962000>,#<TZInfo::TimezoneOffset: 32400,0,JST>>,nil>
Time.zone.period_for_local(Time.zone.now)
=> #<TZInfo::TimezonePeriod: #<TZInfo::TimezoneTransitionDefinition: #<TZInfo::TimeOrDateTime: -577962000>,#<TZInfo::TimezoneOffset: 32400,0,JST>>,nil>
- ↑ TimeWithZone Instance が
TZInfo::Timezone
Class も使用可能にする。