3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails探検録 ActiveSupport 編: TimeZone

Last updated at Posted at 2020-03-01

【概要】

最近、ライブラリを読むのが楽しくて、今まで敬遠していた Rails のソースコードを読み始めたので、記録していく。全部のメソッドは書いてないよ。



※ 例文の実行環境は既存の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>
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 も使用可能にする。
3
0
0

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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?