lib/lazier/datetime.rb in lazier-1.0.7 vs lib/lazier/datetime.rb in lazier-2.0.0

- old
+ new

@@ -17,11 +17,11 @@ # @param short [Boolean] If return the abbreviated representations. # @return [Array] Return string representations of days. def days(short = true) days = ::Lazier.settings.date_names[short ? :short_days : :long_days] (1..7).to_a.collect { |i| - {:value => i.to_s, :label=> days[i - 1]} + {value: i.to_s, label: days[i - 1]} } end # Returns strings representations of months. @@ -30,11 +30,11 @@ # @param short [Boolean] If return the abbreviated representations. # @return [Array] Return string representations of months. def months(short = true) months = ::Lazier.settings.date_names[short ? :short_months : :long_months] (1..12).collect { |i| - {:value => i.to_s.rjust(2, "0"), :label=> months.at(i - 1)} + {value: i.to_s.rjust(2, "0"), label: months.at(i - 1)} } end # Returns a range of years. # @@ -54,11 +54,11 @@ # @param reference [Fixnum] The ending (or middle, if `also_future` is `true`) value of the range. Defaults to the current year. # @param as_objects [Boolean] If to return years in hashes with `:value` and `label` keys. # @return [Array] A range of years. Every entry is def years(offset = 10, also_future = true, reference = nil, as_objects = false) y = reference || ::Date.today.year - (y - offset..(also_future ? y + offset : y)).collect { |year| as_objects ? {:value => year, :label => year} : year } + (y - offset..(also_future ? y + offset : y)).collect { |year| as_objects ? {value: year, label: year} : year } end # Returns all the availabe timezones. # # @return [Array]All the zone available. @@ -123,25 +123,14 @@ # @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 = year % 19 - b = (year / 100.0).floor - c = year % 100 - d = (b / 4.0).floor - e = b % 4 - f = ((b + 8) / 25.0).floor - g = ((b - f + 1) / 3.0).floor - h = ((19 * a) + b - d - g + 15) % 30 - i = (c / 4.0).floor - k = c % 4 - l = (32 + (2 * e) + (2 * i) - h - k) % 7 - m = ((a + (11 * h) + (22 * l)) / 451.0).floor + 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)) - day = ((h + l - (7 * m) + 114) % 31) + 1 - month = ((h + l - (7 * m) + 114) / 31.0).floor ::Date.civil(year, month, day) end # Lookups a custom datetime format. # @see Settings#setup_date_formats @@ -169,10 +158,57 @@ rv = false end rv end + + 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) + [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) + [ + 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) + h = ((19 * a) + x + 15) % 30 + l = (32 + (2 * e) + (2 * i) - h - k) % 7 + + [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 + [((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. # # @return [UTC::Time] The UTC::Time representation of the current datetime. @@ -208,36 +244,12 @@ # @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 - - final_format = ::DateTime.custom_format(format).ensure_string.gsub(/(%{1,2}:?[abz])/i) do |match| - mrv = match - - # Handling of %z is to fix ruby 1.8 bug in OSX: http://bugs.ruby-lang.org/issues/2396 - if match !~ /^%%/ then - case match - when "%a" - mrv = names[:short_days][self.wday] - when "%A" - mrv = names[:long_days][self.wday] - when "%b" - mrv = names[:short_months][self.month - 1] - when "%B" - mrv = names[:long_months][self.month - 1] - when "%z" - mrv = ::Lazier.is_ruby_18? ? self.formatted_offset(false) : nil - when "%:z" - mrv = ::Lazier.is_ruby_18? ? self.formatted_offset(true) : nil - end - end - - mrv ? mrv.sub("%", "%%") : match - end - - self.strftime(final_format) + 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] }) end # Formats a datetime in the current timezone. # # @param format [String] The format to use for formatting. @@ -303,27 +315,17 @@ # @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)" - dst_key = "DST-#{dst_label}" + @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 - if with_dst && @zones_names[dst_key].blank? then - @zones_names[dst_key] = [] - - ::ActiveSupport::TimeZone.all.each do |zone| - zone.aliases.each do |zone_alias| - @zones_names[dst_key] << zone.to_str(zone_alias) - @zones_names[dst_key] << zone.to_str_with_dst(dst_label, nil, zone_alias) if zone.uses_dst? && zone_alias !~ /(#{Regexp.quote(dst_label)})$/ - end - end - - @zones_names[dst_key]= @zones_names[dst_key].uniq.compact.sort { |a,b| ::ActiveSupport::TimeZone.compare(a, b) } # Sort by name - end - - @zones_names[with_dst ? dst_key : "STANDARD"] + @zones_names["#{with_dst ? "DST[#{dst_label}]-" : ""}STANDARD"] end # Returns a string representation of a timezone. # # ```ruby @@ -380,36 +382,21 @@ left.ensure_string.split(" ", 2)[1] <=> right.ensure_string.split(" ", 2)[1] end end # Returns a list of valid aliases (city names) for this timezone (basing on offset). - # - # @param dst_label [String] Label for the DST indication. Defaults to `(DST)`. # @return [Array] A list of aliases for this timezone - def aliases(dst_label = nil) - reference = self.name - reference = self.class::MAPPING[self.name] if self.class::MAPPING.has_key?(self.name) # We are an alias - reference = reference.gsub("_", " ") + def aliases + reference = self.class::MAPPING.fetch(self.name, self.name).gsub("_", " ") - if @aliases.blank? then - # First we search for aliases by name - @aliases = [reference] - - self.class::MAPPING.each do |name, zone| - if zone.gsub("_", " ") == reference then - if name == "International Date Line West" || name == "UTC" || name.include?("(US & Canada)") - @aliases << name - else - @aliases << reference.gsub(/\/.*/, "/" + name) - end - end + @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 - - @aliases = @aliases.uniq.compact.sort - end - - @aliases + }).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. @@ -477,22 +464,21 @@ # # @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) - period = self.dst_period(year) - rv = period ? period.std_offset : 0 - rational ? self.class.rationalize_offset(rv) : rv + self.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) + def dst_offset(rational = false, year = nil, method = :utc_total_offset) period = self.dst_period(year) - rv = period ? period.utc_total_offset : 0 + 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. # \ No newline at end of file