lib/lazier/datetime.rb in lazier-2.4.0 vs lib/lazier/datetime.rb in lazier-2.5.0
- old
+ new
@@ -123,13 +123,15 @@
# @return [Date] The Easter date for the year.
def easter(year = nil)
year = ::Date.today.year if !year.is_integer?
# Compute using Anonymouse Gregorian Algorithm: http://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm
- a, b, c = easter_independent(year)
- x, e, i, k = easter_dependent(b, c)
- day, month = easter_summarize(easter_finalize(a, x, e, i, k))
+ data = easter_start(year)
+ data = easter_part_1(data)
+ data = easter_part_2(year, data)
+ data = easter_part_3(year, data)
+ day, month = easter_end(data)
::Date.civil(year, month, day)
end
# Lookups a custom datetime format.
@@ -163,50 +165,54 @@
private
# Part one of Easter calculation.
#
# @param year [Fixnum] The year to compute the date for.
- # @return [Array] Partial variables for calculus.
- def easter_independent(year)
+ # @return [Array] Partial variables for #easter_part_1.
+ def easter_start(year)
[year % 19, (year / 100.0).floor, year % 100]
end
# Part two of Easter calculation.
- #
- # @param b [Fixnum] Variable from #easter_independent.
- # @param c [Fixnum] Variable from #easter_independent.
- # @return [Array] Partial variables for calculus.
- def easter_dependent(b, c)
+ # @param data [Fixnum] Partial variables from #easter_start.
+ # @return [Array] Partial variables for #easter_part_2.
+ def easter_part_1(data)
+ a, b, c = data
[
b - (b / 4.0).floor - ((b - ((b + 8) / 25.0).floor + 1) / 3.0).floor,
b % 4,
(c / 4.0).floor,
c % 4
]
end
# Part three of Easter calculation.
#
- # @param a [Fixnum] Variable from #easter_independent.
- # @param x [Fixnum] Variable from #easter_independent.
- # @param e [Fixnum] Variable from #easter_dependent.
- # @param i [Fixnum] Variable from #easter_dependent.
- # @param k [Fixnum] Variable from #easter_dependent.
- # @return [Array] Partial variables for calculus.
- def easter_finalize(a, x, e, i, k)
+ # @param data [Fixnum] Partial variables from #easter_part_1.
+ # @return [Array] Partial variables for #easter_part_3.
+ def easter_part_2(year, data)
+ a = year % 19
+ x, e, i, k = data
h = ((19 * a) + x + 15) % 30
- l = (32 + (2 * e) + (2 * i) - h - k) % 7
+ [h, (32 + (2 * e) + (2 * i) - h - k) % 7]
+ end
+ # Part four of Easter calculation
+ # @param data [Arrays] Partial variables from #easter_part_2.
+ # @return [Array] Partial variables for #easter_end.
+ def easter_part_3(year, data)
+ a = year % 19
+ h, l = data
[h, l, ((a + (11 * h) + (22 * l)) / 451.0).floor]
end
# Final part of Easter calculation.
#
- # @param prev [Fixnum] Variable from #easter_finalize.
- # @return [Array] Day and month of Easter daye.
- def easter_summarize(prev)
- h, l, m = prev
+ # @param data [Fixnum] Variable from #easter_part_3.
+ # @return [Array] Day and month of Easter day.
+ def easter_end(data)
+ h, l, m = data
[((h + l - (7 * m) + 114) % 31) + 1, ((h + l - (7 * m) + 114) / 31.0).floor]
end
end
# Returns the UTC::Time representation of the current datetime.
@@ -242,14 +248,11 @@
# @see Settings#setup_date_formats
#
# @param format [String] A format or a custom format name to use for formatting.
# @return [String] The formatted date.
def lstrftime(format = nil)
- rv = nil
- names = ::Lazier.settings.date_names
- substitutions = {"%a" => names[:short_days][self.wday], "%A" => names[:long_days][self.wday], "%b" => names[:short_months][self.month - 1], "%B" => names[:long_months][self.month - 1]}
- self.strftime(::DateTime.custom_format(format).ensure_string.gsub(/(?<!%)(%[ab])/i) {|mo| substitutions[mo] })
+ self.strftime(::DateTime.custom_format(format).ensure_string.gsub(/(?<!%)(%[ab])/i) {|mo| localize_time_component(mo) })
end
# Formats a datetime in the current timezone.
#
# @param format [String] The format to use for formatting.
@@ -264,10 +267,21 @@
# @param format [String] A format or a custom format name.
# @return [String] The formatted date.
def local_lstrftime(format = nil)
(self.respond_to?(:in_time_zone) ? self.in_time_zone : self).lstrftime(format)
end
+
+ private
+ # Returns a component of the date in the current locale.
+ #
+ # @param component [String] The component to localize.
+ # @return [String] The localized component.
+ def localize_time_component(component)
+ type = {"%a" => :short_days, "%A" => :long_days, "%b" => :short_months, "%B" => :long_months}.fetch(component, "")
+ index = component =~ /%a/i ? self.wday : self.month - 1
+ ::Lazier.settings.date_names.fetch(type, [])[index]
+ end
end
# Extensions for timezone objects.
module TimeZone
extend ::ActiveSupport::Concern
@@ -317,13 +331,11 @@
# @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.collect(&:to_s) }
- @zones_names["DST[#{dst_label}]-STANDARD"] ||= ::ActiveSupport::TimeZone.all.collect { |zone|
- zone.aliases.collect { |zone_alias| [zone.to_str(zone_alias), (zone.uses_dst? && zone_alias !~ /(#{Regexp.quote(dst_label)})$/) ? zone.to_str_with_dst(dst_label, nil, zone_alias) : nil] }
- }.flatten.compact.uniq.sort { |a,b| ::ActiveSupport::TimeZone.compare(a, b) } # Sort by name
+ @zones_names["DST[#{dst_label}]-STANDARD"] ||= ::ActiveSupport::TimeZone.all.collect { |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.
@@ -379,24 +391,28 @@
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)")
+ zone.aliases.collect { |zone_alias|
+ [zone.to_str(zone_alias), (zone.uses_dst? && zone_alias !~ /(#{Regexp.quote(dst_label)})$/) ? zone.to_str_with_dst(dst_label, nil, zone_alias) : nil]
+ }
+ 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(self.name, self.name).gsub("_", " ")
-
- @aliases ||= ([reference] + self.class::MAPPING.collect { |name, zone|
- if zone.gsub("_", " ") == reference then
- (["International Date Line West", "UTC"].include?(name) || name.include?("(US & Canada)")) ? name : reference.gsub(/\/.*/, "/#{name}")
- else
- nil
- end
- }).uniq.compact.sort
+ @aliases ||= ([reference] + self.class::MAPPING.collect { |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.
@@ -541,7 +557,22 @@
# @return [String] The parametized 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, with_offset = true, year = nil, name = nil)
rv = self.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 then
+ (["International Date Line West", "UTC"].include?(name) || name.include?("(US & Canada)")) ? name : reference.gsub(/\/.*/, "/#{name}")
+ else
+ nil
+ end
+ end
end
end
\ No newline at end of file