跳至内容 跳至搜索

Active Support 时区

The TimeZone 类是 TZInfo::Timezone 实例的包装器。它允许我们执行以下操作

  • 将 TZInfo 提供的时区集限制为 134 个有意义的子集。

  • 检索和显示具有更友好名称的时区(例如,“东部 Time (美国和加拿大)”而不是“America/New_York”)。

  • 仅在需要时延迟加载 TZInfo::Timezone 实例。

  • 通过 TimeZone 的 localparseatnow 方法创建 ActiveSupport::TimeWithZone 实例。

如果您在 Rails 应用程序中设置了 config.time_zone,您可以通过 Time.zone 访问此 TimeZone 对象

# application.rb:
class Application < Rails::Application
  config.time_zone = 'Eastern Time (US & Canada)'
end

Time.zone      # => #<ActiveSupport::TimeZone:0x514834...>
Time.zone.name # => "Eastern Time (US & Canada)"
Time.zone.now  # => Sun, 18 May 2008 14:30:44 EDT -04:00
方法
#
A
C
F
I
L
M
N
P
R
S
T
U
Y
包含的模块

常量

MAPPING = { "International Date Line West" => "Etc/GMT+12", "Midway Island" => "Pacific/Midway", "American Samoa" => "Pacific/Pago_Pago", "Hawaii" => "Pacific/Honolulu", "Alaska" => "America/Juneau", "Pacific Time (US & Canada)" => "America/Los_Angeles", "Tijuana" => "America/Tijuana", "Mountain Time (US & Canada)" => "America/Denver", "Arizona" => "America/Phoenix", "Chihuahua" => "America/Chihuahua", "Mazatlan" => "America/Mazatlan", "Central Time (US & Canada)" => "America/Chicago", "Saskatchewan" => "America/Regina", "Guadalajara" => "America/Mexico_City", "Mexico City" => "America/Mexico_City", "Monterrey" => "America/Monterrey", "Central America" => "America/Guatemala", "Eastern Time (US & Canada)" => "America/New_York", "Indiana (East)" => "America/Indiana/Indianapolis", "Bogota" => "America/Bogota", "Lima" => "America/Lima", "Quito" => "America/Lima", "Atlantic Time (Canada)" => "America/Halifax", "Caracas" => "America/Caracas", "La Paz" => "America/La_Paz", "Santiago" => "America/Santiago", "Newfoundland" => "America/St_Johns", "Brasilia" => "America/Sao_Paulo", "Buenos Aires" => "America/Argentina/Buenos_Aires", "Montevideo" => "America/Montevideo", "Georgetown" => "America/Guyana", "Puerto Rico" => "America/Puerto_Rico", "Greenland" => "America/Godthab", "Mid-Atlantic" => "Atlantic/South_Georgia", "Azores" => "Atlantic/Azores", "Cape Verde Is." => "Atlantic/Cape_Verde", "Dublin" => "Europe/Dublin", "Edinburgh" => "Europe/London", "Lisbon" => "Europe/Lisbon", "London" => "Europe/London", "Casablanca" => "Africa/Casablanca", "Monrovia" => "Africa/Monrovia", "UTC" => "Etc/UTC", "Belgrade" => "Europe/Belgrade", "Bratislava" => "Europe/Bratislava", "Budapest" => "Europe/Budapest", "Ljubljana" => "Europe/Ljubljana", "Prague" => "Europe/Prague", "Sarajevo" => "Europe/Sarajevo", "Skopje" => "Europe/Skopje", "Warsaw" => "Europe/Warsaw", "Zagreb" => "Europe/Zagreb", "Brussels" => "Europe/Brussels", "Copenhagen" => "Europe/Copenhagen", "Madrid" => "Europe/Madrid", "Paris" => "Europe/Paris", "Amsterdam" => "Europe/Amsterdam", "Berlin" => "Europe/Berlin", "Bern" => "Europe/Zurich", "Zurich" => "Europe/Zurich", "Rome" => "Europe/Rome", "Stockholm" => "Europe/Stockholm", "Vienna" => "Europe/Vienna", "West Central Africa" => "Africa/Algiers", "Bucharest" => "Europe/Bucharest", "Cairo" => "Africa/Cairo", "Helsinki" => "Europe/Helsinki", "Kyiv" => "Europe/Kiev", "Riga" => "Europe/Riga", "Sofia" => "Europe/Sofia", "Tallinn" => "Europe/Tallinn", "Vilnius" => "Europe/Vilnius", "Athens" => "Europe/Athens", "Istanbul" => "Europe/Istanbul", "Minsk" => "Europe/Minsk", "Jerusalem" => "Asia/Jerusalem", "Harare" => "Africa/Harare", "Pretoria" => "Africa/Johannesburg", "Kaliningrad" => "Europe/Kaliningrad", "Moscow" => "Europe/Moscow", "St. Petersburg" => "Europe/Moscow", "Volgograd" => "Europe/Volgograd", "Samara" => "Europe/Samara", "Kuwait" => "Asia/Kuwait", "Riyadh" => "Asia/Riyadh", "Nairobi" => "Africa/Nairobi", "Baghdad" => "Asia/Baghdad", "Tehran" => "Asia/Tehran", "Abu Dhabi" => "Asia/Muscat", "Muscat" => "Asia/Muscat", "Baku" => "Asia/Baku", "Tbilisi" => "Asia/Tbilisi", "Yerevan" => "Asia/Yerevan", "Kabul" => "Asia/Kabul", "Ekaterinburg" => "Asia/Yekaterinburg", "Islamabad" => "Asia/Karachi", "Karachi" => "Asia/Karachi", "Tashkent" => "Asia/Tashkent", "Chennai" => "Asia/Kolkata", "Kolkata" => "Asia/Kolkata", "Mumbai" => "Asia/Kolkata", "New Delhi" => "Asia/Kolkata", "Kathmandu" => "Asia/Kathmandu", "Astana" => "Asia/Dhaka", "Dhaka" => "Asia/Dhaka", "Sri Jayawardenepura" => "Asia/Colombo", "Almaty" => "Asia/Almaty", "Novosibirsk" => "Asia/Novosibirsk", "Rangoon" => "Asia/Rangoon", "Bangkok" => "Asia/Bangkok", "Hanoi" => "Asia/Bangkok", "Jakarta" => "Asia/Jakarta", "Krasnoyarsk" => "Asia/Krasnoyarsk", "Beijing" => "Asia/Shanghai", "Chongqing" => "Asia/Chongqing", "Hong Kong" => "Asia/Hong_Kong", "Urumqi" => "Asia/Urumqi", "Kuala Lumpur" => "Asia/Kuala_Lumpur", "Singapore" => "Asia/Singapore", "Taipei" => "Asia/Taipei", "Perth" => "Australia/Perth", "Irkutsk" => "Asia/Irkutsk", "Ulaanbaatar" => "Asia/Ulaanbaatar", "Seoul" => "Asia/Seoul", "Osaka" => "Asia/Tokyo", "Sapporo" => "Asia/Tokyo", "Tokyo" => "Asia/Tokyo", "Yakutsk" => "Asia/Yakutsk", "Darwin" => "Australia/Darwin", "Adelaide" => "Australia/Adelaide", "Canberra" => "Australia/Canberra", "Melbourne" => "Australia/Melbourne", "Sydney" => "Australia/Sydney", "Brisbane" => "Australia/Brisbane", "Hobart" => "Australia/Hobart", "Vladivostok" => "Asia/Vladivostok", "Guam" => "Pacific/Guam", "Port Moresby" => "Pacific/Port_Moresby", "Magadan" => "Asia/Magadan", "Srednekolymsk" => "Asia/Srednekolymsk", "Solomon Is." => "Pacific/Guadalcanal", "New Caledonia" => "Pacific/Noumea", "Fiji" => "Pacific/Fiji", "Kamchatka" => "Asia/Kamchatka", "Marshall Is." => "Pacific/Majuro", "Auckland" => "Pacific/Auckland", "Wellington" => "Pacific/Auckland", "Nuku'alofa" => "Pacific/Tongatapu", "Tokelau Is." => "Pacific/Fakaofo", "Chatham Is." => "Pacific/Chatham", "Samoa" => "Pacific/Apia" }
 

键是 Rails TimeZone 名称,值是 TZInfo 标识符。

属性

[R] name
[R] tzinfo

类公共方法

[](arg)

查找特定的时区对象。如果参数是字符串,则将其解释为要查找的时区的名称。如果它是数值,则它是要查找的时区的时差或秒差。(将返回第一个具有该时差的时区。)如果系统中没有这样的时区,则返回 nil

# File activesupport/lib/active_support/values/time_zone.rb, line 232
def [](arg)
  case arg
  when self
    arg
  when String
    begin
      @lazy_zones_map[arg] ||= create(arg)
    rescue TZInfo::InvalidTimezoneIdentifier
      nil
    end
  when TZInfo::Timezone
    @lazy_zones_map[arg.name] ||= create(arg.name, nil, arg)
  when Numeric, ActiveSupport::Duration
    arg *= 3600 if arg.abs <= 13
    all.find { |z| z.utc_offset == arg.to_i }
  else
    raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
  end
end

all()

返回所有 TimeZone 对象的数组。在许多情况下,每个时区有多个 TimeZone 对象,以便用户更容易找到自己的时区。

# File activesupport/lib/active_support/values/time_zone.rb, line 223
def all
  @zones ||= zones_map.values.sort
end

country_zones(country_code)

一个方便的方法,用于返回指定国家/地区(使用其 ISO 3166-1 Alpha2 代码)的时区的 TimeZone 对象集合。

# File activesupport/lib/active_support/values/time_zone.rb, line 260
def country_zones(country_code)
  code = country_code.to_s.upcase
  @country_zones[code] ||= load_country_zones(code)
end

create(name)

别名:new

find_tzinfo(name)

# File activesupport/lib/active_support/values/time_zone.rb, line 207
def find_tzinfo(name)
  TZInfo::Timezone.get(MAPPING[name] || name)
end

new(name)

返回具有给定名称的 TimeZone 实例,如果不存在这样的 TimeZone 实例,则返回 nil。(这用于支持使用 composed_of 宏来使用此类。)

也称为:create
# File activesupport/lib/active_support/values/time_zone.rb, line 216
def new(name)
  self[name]
end

new(name, utc_offset = nil, tzinfo = nil)

使用给定的名称和偏移量创建一个新的 TimeZone 对象。偏移量是该时区相对于 UTC(GMT)的秒数。选择秒作为偏移量单位,因为这是 Ruby 用于表示时区偏移量的单位(请参阅 Time#utc_offset)。

# File activesupport/lib/active_support/values/time_zone.rb, line 303
def initialize(name, utc_offset = nil, tzinfo = nil)
  @name = name
  @utc_offset = utc_offset
  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
end

seconds_to_utc_offset(seconds, colon = true)

假设 self 代表相对于 UTC 的偏移量(以秒为单位,如 Time#utc_offset 返回),并将此转换为 +HH:MM 格式的字符串。

ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
# File activesupport/lib/active_support/values/time_zone.rb, line 199
def seconds_to_utc_offset(seconds, colon = true)
  format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
  sign = (seconds < 0 ? "-" : "+")
  hours = seconds.abs / 3600
  minutes = (seconds.abs % 3600) / 60
  format % [sign, hours, minutes]
end

us_zones()

一个方便的方法,用于返回美国时区的 TimeZone 对象集合。

# File activesupport/lib/active_support/values/time_zone.rb, line 254
def us_zones
  country_zones(:us)
end

实例公共方法

<=>(zone)

将此时区与参数进行比较。首先根据它们的偏移量进行比较,然后按名称进行比较。

# File activesupport/lib/active_support/values/time_zone.rb, line 326
def <=>(zone)
  return unless zone.respond_to? :utc_offset
  result = (utc_offset <=> zone.utc_offset)
  result = (name <=> zone.name) if result == 0
  result
end

=~(re)

name 和 TZInfo 标识符与提供的正则表达式进行比较,如果找到匹配项,则返回 true

# File activesupport/lib/active_support/values/time_zone.rb, line 335
def =~(re)
  re === name || re === MAPPING[name]
end

at(*args)

Method 用于从 Unix 纪元以来的秒数创建 self 时区中的新 ActiveSupport::TimeWithZone 实例。

Time.zone = 'Hawaii'        # => "Hawaii"
Time.utc(2000).to_f         # => 946684800.0
Time.zone.at(946684800.0)   # => Fri, 31 Dec 1999 14:00:00 HST -10:00

可以提供第二个参数来指定亚秒精度。

Time.zone = 'Hawaii'                # => "Hawaii"
Time.at(946684800, 123456.789).nsec # => 123456789
# File activesupport/lib/active_support/values/time_zone.rb, line 372
def at(*args)
  Time.at(*args).utc.in_time_zone(self)
end

formatted_offset(colon = true, alternate_utc_string = nil)

返回一个格式化的字符串,表示相对于 UTC 的偏移量,如果时区已经是 UTC,则返回一个备用字符串。

zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
zone.formatted_offset        # => "-06:00"
zone.formatted_offset(false) # => "-0600"
# File activesupport/lib/active_support/values/time_zone.rb, line 320
def formatted_offset(colon = true, alternate_utc_string = nil)
  utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
end

iso8601(str)

方法 用于从 ISO 8601 字符串创建新的 ActiveSupport::TimeWithZone 实例,该实例位于 self 的时区中。

Time.zone = 'Hawaii'                     # => "Hawaii"
Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00

如果时间组件缺失,则将其设置为零。

Time.zone = 'Hawaii'            # => "Hawaii"
Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00

如果字符串无效,则会引发 ArgumentError,这与 parse 不同,parse 在给定无效日期字符串时通常返回 nil

# File activesupport/lib/active_support/values/time_zone.rb, line 389
def iso8601(str)
  # Historically `Date._iso8601(nil)` returns `{}`, but in the `date` gem versions `3.2.1`, `3.1.2`, `3.0.2`,
  # and `2.0.1`, `Date._iso8601(nil)` raises `TypeError` https://github.com/ruby/date/issues/39
  # Future `date` releases are expected to revert back to the original behavior.
  raise ArgumentError, "invalid date" if str.nil?

  parts = Date._iso8601(str)

  year = parts.fetch(:year)

  if parts.key?(:yday)
    ordinal_date = Date.ordinal(year, parts.fetch(:yday))
    month = ordinal_date.month
    day = ordinal_date.day
  else
    month = parts.fetch(:mon)
    day = parts.fetch(:mday)
  end

  time = Time.new(
    year,
    month,
    day,
    parts.fetch(:hour, 0),
    parts.fetch(:min, 0),
    parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
    parts.fetch(:offset, 0)
  )

  if parts[:offset]
    TimeWithZone.new(time.utc, self)
  else
    TimeWithZone.new(nil, self, time)
  end

rescue Date::Error, KeyError
  raise ArgumentError, "invalid date"
end

local(*args)

方法 用于从给定值创建新的 ActiveSupport::TimeWithZone 实例,该实例位于 self 的时区中。

Time.zone = 'Hawaii'                    # => "Hawaii"
Time.zone.local(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00
# File activesupport/lib/active_support/values/time_zone.rb, line 356
def local(*args)
  time = Time.utc(*args)
  ActiveSupport::TimeWithZone.new(nil, self, time)
end

local_to_utc(time, dst = true)

将给定时间调整为 UTC 中的同步时间。返回一个 Time.utc() 实例。

# File activesupport/lib/active_support/values/time_zone.rb, line 544
def local_to_utc(time, dst = true)
  tzinfo.local_to_utc(time, dst)
end

match?(re)

name 和 TZInfo 标识符与提供的正则表达式进行比较,如果找到匹配项,则返回 true

# File activesupport/lib/active_support/values/time_zone.rb, line 341
def match?(re)
  (re == name) || (re == MAPPING[name]) ||
    ((Regexp === re) && (re.match?(name) || re.match?(MAPPING[name])))
end

now()

返回一个表示当前时间在self表示的时区中的ActiveSupport::TimeWithZone实例。

Time.zone = 'Hawaii'  # => "Hawaii"
Time.zone.now         # => Wed, 23 Jan 2008 20:24:27 HST -10:00
# File activesupport/lib/active_support/values/time_zone.rb, line 509
def now
  time_now.utc.in_time_zone(self)
end

parse(str, now = now())

用于从解析的字符串创建新的ActiveSupport::TimeWithZone实例,该实例位于self的时区中。

Time.zone = 'Hawaii'                   # => "Hawaii"
Time.zone.parse('1999-12-31 14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00

如果字符串中缺少上层组件,则会从TimeZone#now提供。

Time.zone.now               # => Fri, 31 Dec 1999 14:00:00 HST -10:00
Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00

但是,如果未提供日期组件,但提供了任何其他上层组件,则月份的日期默认为 1。

Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00

如果字符串无效,则可能会引发ArgumentError

# File activesupport/lib/active_support/values/time_zone.rb, line 446
def parse(str, now = now())
  parts_to_time(Date._parse(str, false), now)
end

period_for_local(time, dst = true)

可用,以便TimeZone实例像TZInfo::Timezone实例一样响应。

# File activesupport/lib/active_support/values/time_zone.rb, line 556
def period_for_local(time, dst = true)
  tzinfo.period_for_local(time, dst) { |periods| periods.last }
end

period_for_utc(time)

可用,以便TimeZone实例像TZInfo::Timezone实例一样响应。

# File activesupport/lib/active_support/values/time_zone.rb, line 550
def period_for_utc(time)
  tzinfo.period_for_utc(time)
end

rfc3339(str)

用于从 RFC 3339 字符串在self的时区中创建新的ActiveSupport::TimeWithZone实例。

Time.zone = 'Hawaii'                     # => "Hawaii"
Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00

如果时间或区域组件丢失,则会引发ArgumentError。这比parseiso8601严格得多,后者允许缺少组件。

Time.zone = 'Hawaii'            # => "Hawaii"
Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
# File activesupport/lib/active_support/values/time_zone.rb, line 462
def rfc3339(str)
  parts = Date._rfc3339(str)

  raise ArgumentError, "invalid date" if parts.empty?

  time = Time.new(
    parts.fetch(:year),
    parts.fetch(:mon),
    parts.fetch(:mday),
    parts.fetch(:hour),
    parts.fetch(:min),
    parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
    parts.fetch(:offset)
  )

  TimeWithZone.new(time.utc, self)
end

strptime(str, format, now = now())

根据format解析str,并返回一个ActiveSupport::TimeWithZone

假设strself 时区中的时间,除非format 包含明确的时区。(这与parse 的行为相同。)无论哪种情况,返回的 TimeWithZone 都有self 的时区。

Time.zone = 'Hawaii'                   # => "Hawaii"
Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S') # => Fri, 31 Dec 1999 14:00:00 HST -10:00

如果字符串中缺少上层组件,则会从TimeZone#now提供。

Time.zone.now                              # => Fri, 31 Dec 1999 14:00:00 HST -10:00
Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00

但是,如果未提供日期组件,但提供了任何其他上层组件,则月份的日期默认为 1。

Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
# File activesupport/lib/active_support/values/time_zone.rb, line 500
def strptime(str, format, now = now())
  parts_to_time(DateTime._strptime(str, format), now)
end

to_s()

返回此时区的文本表示形式。

# File activesupport/lib/active_support/values/time_zone.rb, line 347
def to_s
  "(GMT#{formatted_offset}) #{name}"
end

today()

返回此时区的当前日期。

# File activesupport/lib/active_support/values/time_zone.rb, line 514
def today
  tzinfo.now.to_date
end

tomorrow()

返回此时区的下一个日期。

# File activesupport/lib/active_support/values/time_zone.rb, line 519
def tomorrow
  today + 1
end

utc_offset()

返回此时区相对于 UTC 的偏移量(以秒为单位)。

# File activesupport/lib/active_support/values/time_zone.rb, line 310
def utc_offset
  @utc_offset || tzinfo&.current_period&.base_utc_offset
end

utc_to_local(time)

将给定时间调整为self 所代表的时区中的同时时间。返回具有适当偏移量的本地时间 - 如果你想要一个 ActiveSupport::TimeWithZone 实例,请使用 Time#in_time_zone() 代替。

从 tzinfo 2 开始,utc_to_local 返回一个具有非零 utc_offset 的 Time。有关更多信息,请参阅utc_to_local_returns_utc_offset_times 配置。

# File activesupport/lib/active_support/values/time_zone.rb, line 535
def utc_to_local(time)
  tzinfo.utc_to_local(time).yield_self do |t|
    ActiveSupport.utc_to_local_returns_utc_offset_times ?
      t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction * 1_000_000)
  end
end

yesterday()

返回此时区的上一个日期。

# File activesupport/lib/active_support/values/time_zone.rb, line 524
def yesterday
  today - 1
end