lib/lazier/datetime.rb in lazier-3.5.2 vs lib/lazier/datetime.rb in lazier-3.5.3
- old
+ new
@@ -271,298 +271,6 @@
type = {"%a" => :short_days, "%A" => :long_days, "%b" => :short_months, "%B" => :long_months}.fetch(component, "")
index = component =~ /%a/i ? wday : month - 1
::Lazier.settings.date_names[type][index]
end
end
-
- # Extensions for timezone objects.
- module TimeZone
- extend ::ActiveSupport::Concern
-
- # General methods.
- module ClassMethods
- # Returns an offset in rational value.
- #
- # @param offset [Fixnum] The offset to convert.
- # @return [Rational] The converted offset.
- def rationalize_offset(offset)
- ::TZInfo::OffsetRationals.rational_for_offset(offset.is_a?(::Fixnum) ? offset : offset.offset)
- end
-
- # Returns a +HH:MM formatted representation of the offset.
- #
- # @param offset [Rational|Fixnum] The offset to represent, in seconds or as a rational.
- # @param colon [Boolean] If to put the colon in the output string.
- # @return [String] The formatted offset.
- def format_offset(offset, colon = true)
- seconds_to_utc_offset(offset.is_a?(::Rational) ? (offset * 86_400).to_i : offset, colon)
- end
-
- # Find a zone by its name.
- #
- # @param name [String] The zone name.
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- # @return [TimeZone] A timezone or `nil` if no zone was found.
- def find(name, dst_label = nil)
- catch(:zone) do
- ::ActiveSupport::TimeZone.all.each do |zone|
- zone.aliases.each do |zone_alias|
- throw(:zone, zone) if [zone.to_str(zone_alias), zone.to_str_with_dst(dst_label, nil, zone_alias)].include?(name)
- end
- end
-
- nil
- end
- end
-
- # Returns a list of names of all timezones.
- #
- # @param with_dst [Boolean] If include DST version of the zones.
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- # @return [Array] A list of names of timezones.
- def list_all(with_dst = true, dst_label = nil)
- dst_label ||= "(DST)"
-
- @zones_names ||= { "STANDARD" => ::ActiveSupport::TimeZone.all.map(&:to_s) }
- @zones_names["DST[#{dst_label}]-STANDARD"] ||= ::ActiveSupport::TimeZone.all
- .map { |zone| fetch_aliases(zone, dst_label) }.flatten.compact.uniq
- .sort { |a, b| ::ActiveSupport::TimeZone.compare(a, b) } # Sort by name
-
- @zones_names["#{with_dst ? "DST[#{dst_label}]-" : ""}STANDARD"]
- end
-
- # Returns a string representation of a timezone.
- #
- # ```ruby
- # DateTime.parameterize_zone(ActiveSupport::TimeZone["Pacific Time (US & Canada)"])
- # # => "-0800@pacific-time-us-canada"
- # ```
- # @param tz [TimeZone] The zone to represent.
- # @param with_offset [Boolean] If to include offset into the representation.
- # @return [String] A string representation which can be used for searches.
- def parameterize_zone(tz, with_offset = true)
- tz = tz.to_s unless tz.is_a?(::String)
- mo = /^(\([a-z]+([+-])(\d{2})(:?)(\d{2})\)\s(.+))$/i.match(tz)
-
- if mo
- with_offset ? "#{mo[2]}#{mo[3]}#{mo[5]}@#{mo[6].to_s.parameterize}" : mo[6].to_s.parameterize
- elsif !with_offset then
- tz.gsub(/^([+-]?(\d{2})(:?)(\d{2})@)/, "")
- else
- tz.parameterize
- end
- end
-
- # Finds a parameterized timezone.
- # @see DateTime#parameterize_zone
- #
- # @param tz [String] The zone to unparameterize.
- # @param as_string [Boolean] If return just the zone name.
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- # @return [String|TimeZone] The found timezone or `nil` if the zone is not valid.
- def unparameterize_zone(tz, as_string = false, dst_label = nil)
- tz = parameterize_zone(tz, false)
- rv = find_parameterized_zone(dst_label, /(#{Regexp.quote(tz)})$/)
-
- if rv
- as_string ? rv : find(rv, dst_label)
- else
- nil
- end
- end
-
- # Compares two timezones. They are sorted by the location name.
- #
- # @param left [String|TimeZone] The first zone name to compare.
- # @param right [String|TimeZone] The second zone name to compare.
- # @return [Fixnum] The result of comparison, like Ruby's operator `<=>`.
- def compare(left, right)
- left = left.to_str if left.is_a?(::ActiveSupport::TimeZone)
- right = right.to_str if right.is_a?(::ActiveSupport::TimeZone)
- left.ensure_string.split(" ", 2)[1] <=> right.ensure_string.split(" ", 2)[1]
- end
-
- private
-
- # Returns a list of aliases for a given time zone.
- #
- # @param zone [ActiveSupport::TimeZone] The zone.
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- def fetch_aliases(zone, dst_label = "(DST)")
- matcher = /(#{Regexp.quote(dst_label)})$/
-
- zone.aliases.map { |zone_alias|
- [zone.to_str(zone_alias), (zone.uses_dst? && zone_alias !~ matcher) ? zone.to_str_with_dst(dst_label, nil, zone_alias) : nil]
- }
- end
-
- # Finds a parameterized timezone.
- #
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- # @param matcher [Regexp] The expression to match.
- # @return [TimeZone] The found timezone or `nil` if the zone is not valid.
- def find_parameterized_zone(dst_label, matcher)
- catch(:zone) do
- list_all(true, dst_label).each do |zone|
- throw(:zone, zone) if parameterize_zone(zone, false) =~ matcher
- end
-
- nil
- end
- end
- end
-
- # Returns a list of valid aliases (city names) for this timezone (basing on offset).
- # @return [Array] A list of aliases for this timezone
- def aliases
- reference = self.class::MAPPING.fetch(name, name).gsub("_", " ")
- @aliases ||= ([reference] + self.class::MAPPING.map { |name, zone| format_alias(name, zone, reference) }).uniq.compact.sort
- end
-
- # Returns the current offset for this timezone, taking care of Daylight Saving Time (DST).
- #
- # @param rational [Boolean] If to return the offset as a Rational.
- # @param date [DateTime] The date to consider. Defaults to now.
- # @return [Fixnum|Rational] The offset of this timezone.
- def current_offset(rational = false, date = nil)
- date ||= ::DateTime.now
- rv = (period_for_utc(date.utc).dst? ? dst_offset : offset)
- rational ? self.class.rationalize_offset(rv) : rv
- end
-
- # Returns the current alias for this timezone.
- #
- # @return [String] The current alias or the first alias of the current timezone.
- def current_alias
- identifier = tzinfo.identifier
-
- catch(:alias) do
- aliases.each do |a|
- throw(:alias, a) if a == identifier
- end
-
- aliases.first
- end
- end
-
- # Returns the standard offset for this timezone.
- #
- # @param rational [Boolean] If to return the offset as a Rational.
- # @return [Fixnum|Rational] The offset of this timezone.
- def offset(rational = false)
- rational ? self.class.rationalize_offset(utc_offset) : utc_offset
- end
-
- # Gets a period for this timezone when the Daylight Saving Time (DST) is active (it takes care of different hemispheres).
- #
- # @param year [Fixnum] The year to which refer to. Defaults to the current year.
- # @return [TimezonePeriod] A period when the Daylight Saving Time (DST) is active or `nil` if the timezone doesn't use DST for that year.
- def dst_period(year = nil)
- year ||= ::Date.today.year
-
- northern_summer = ::DateTime.civil(year, 7, 15).utc # This is a representation of a summer period in the Northern Hemisphere.
- southern_summer = ::DateTime.civil(year, 1, 15).utc # This is a representation of a summer period in the Southern Hemisphere.
-
- period = period_for_utc(northern_summer)
- period = period_for_utc(southern_summer) unless period.dst?
- period.dst? ? period : nil
- end
-
- # Checks if the timezone uses Daylight Saving Time (DST) for that date or year.
- #
- # @param reference [Object] The date or year to check. Defaults to the current year.
- # @return [Boolean] `true` if the zone uses DST for that date or year, `false` otherwise.
- def uses_dst?(reference = nil)
- if reference.respond_to?(:year) && reference.respond_to?(:utc) # This is a date like object
- dst_period(reference.year).present? && period_for_utc(reference.utc).dst?
- else
- dst_period(reference).present?
- end
- end
-
- # Return the correction applied to the standard offset the timezone when the Daylight Saving Time (DST) is active.
- #
- # @param rational [Boolean] If to return the offset as a Rational.
- # @param year [Fixnum] The year to which refer to. Defaults to the current year.
- # @return [Fixnum|Rational] The correction for dst.
- def dst_correction(rational = false, year = nil)
- dst_offset(rational, year, :std_offset)
- end
-
- # Returns the standard offset for this timezone timezone when the Daylight Saving Time (DST) is active.
- #
- # @param rational [Boolean] If to return the offset as a Rational.
- # @param year [Fixnum] The year to which refer to. Defaults to the current year.
- # @param method [Symbol] The method to use for getting the offset. Default is total offset from UTC.
- # @return [Fixnum|Rational] The DST offset for this timezone or `0`, if the timezone doesn't use DST for that year.
- def dst_offset(rational = false, year = nil, method = :utc_total_offset)
- period = dst_period(year)
- rv = period ? period.send(method) : 0
- rational ? self.class.rationalize_offset(rv) : rv
- end
-
- # Returns the name for this zone with Daylight Saving Time (DST) active.
- #
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- # @param year [Fixnum] The year to which refer to. Defaults to the current year.
- # @param name [String] The name to use for this zone. Defaults to the zone name.
- # @return [String] The name for the zone with DST or `nil`, if the timezone doesn't use DST for that year.
- def dst_name(dst_label = nil, year = nil, name = nil)
- uses_dst?(year) ? "#{name || self.name} #{dst_label || "(DST)"}" : nil
- end
-
- # Returns the name for this zone with Daylight Saving Time (DST) active.
- #
- # @param name [String] The name to use for this zone. Defaults to the zone name.
- # @param colon [Boolean] If to put the colon in the output string.
- # @return [String] The name for this zone.
- def to_str(name = nil, colon = true)
- "(GMT#{formatted_offset(colon)}) #{name || current_alias}"
- end
-
- # Returns a string representation for this zone with Daylight Saving Time (DST) active.
- #
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- # @param year [Fixnum] The year to which refer to. Defaults to the current year.
- # @param name [String] The name to use for this zone. Defaults to the zone name.
- # @return [String] The string representation for the zone with DST or `nil`, if the timezone doesn't use DST for that year.
- def to_str_with_dst(dst_label = nil, year = nil, name = nil)
- uses_dst?(year) ? "(GMT#{self.class.seconds_to_utc_offset(dst_period(year).utc_total_offset)}) #{name || current_alias} #{dst_label || "(DST)"}" : nil
- end
-
- # Returns a parameterized string representation for this zone.
- #
- # @param with_offset [Boolean] If to include offset into the representation.
- # @param name [String] The name to use for this zone. Defaults to the zone name.
- # @return [String] The parameterized string representation for this zone.
- def to_str_parameterized(with_offset = true, name = nil)
- ::ActiveSupport::TimeZone.parameterize_zone(name || to_str, with_offset)
- end
-
- # Returns a parameterized string representation for this zone with Daylight Saving Time (DST) active.
- #
- # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`.
- # @param year [Fixnum] The year to which refer to. Defaults to the current year.
- # @param name [String] The name to use for this zone. Defaults to the zone name.
- # @return [String] The parameterized string representation for this zone with DST or `nil`, if the timezone doesn't use DST for that year.
- def to_str_with_dst_parameterized(dst_label = nil, year = nil, name = nil)
- rv = to_str_with_dst(dst_label, year, name)
- rv ? ::ActiveSupport::TimeZone.parameterize_zone(rv) : nil
- end
-
- private
-
- # Formats a time zone alias.
- #
- # @param name [String] The zone name.
- # @param zone [String] The zone.
- # @param reference [String] The main name for the zone.
- # @return [String|nil] The formatted alias.
- def format_alias(name, zone, reference)
- if zone.gsub("_", " ") == reference
- ["International Date Line West", "UTC"].include?(name) || name.include?("(US & Canada)") ? name : reference.gsub(/\/.*/, "/#{name}")
- else
- nil
- end
- end
- end
end