now for ruby time

ruby - for - cómo convertir 270921sec en días+horas+minutos+segundo?(rubí)



ruby puts date time (8)

Tengo una cantidad de segundos. Digamos 270921. ¿Cómo puedo mostrar ese número diciendo que es xx días, aa horas, zz minutos, segundos ww?


Esperaba que hubiera una manera más fácil que utilizar DivDod, pero esta es la manera más SECA y reutilizable que he encontrado para hacerlo:

def seconds_to_units(seconds) ''%d days, %d hours, %d minutes, %d seconds'' % # the .reverse lets us put the larger units first for readability [24,60,60].reverse.inject([seconds]) {|result, unitsize| result[0,0] = result.shift.divmod(unitsize) result } end

El método se ajusta fácilmente cambiando la cadena de formato y la primera matriz en línea (es decir, la [24,60,60]).

Versión mejorada

class TieredUnitFormatter # if you set this, ''%d'' must appear as many times as there are units attr_accessor :format_string def initialize(unit_names=%w(days hours minutes seconds), conversion_factors=[24, 60, 60]) @unit_names = unit_names @factors = conversion_factors @format_string = unit_names.map {|name| "%d #{name}" }.join('', '') # the .reverse helps us iterate more effectively @reversed_factors = @factors.reverse end # e.g. seconds def format(smallest_unit_amount) parts = split(smallest_unit_amount) @format_string % parts end def split(smallest_unit_amount) # go from smallest to largest unit @reversed_factors.inject([smallest_unit_amount]) {|result, unitsize| # Remove the most significant item (left side), convert it, then # add the 2-element array to the left side of the result. result[0,0] = result.shift.divmod(unitsize) result } end end

Ejemplos:

fmt = TieredUnitFormatter.new fmt.format(270921) # => "3 days, 3 hours, 15 minutes, 21 seconds" fmt = TieredUnitFormatter.new(%w(minutes seconds), [60]) fmt.format(5454) # => "90 minutes, 54 seconds" fmt.format_string = ''%d:%d'' fmt.format(5454) # => "90:54"

Tenga en cuenta que format_string no le permitirá cambiar el orden de las partes (siempre es el valor más significativo al menos). Para un control más detallado, puede usar split y manipular los valores usted mismo.


Modifiqué la respuesta dada por @Mike para agregar formato dinámico basado en el tamaño del resultado

def formatted_duration(total_seconds) dhms = [60, 60, 24].reduce([total_seconds]) { |m,o| m.unshift(m.shift.divmod(o)).flatten } return "%d days %d hours %d minutes %d seconds" % dhms unless dhms[0].zero? return "%d hours %d minutes %d seconds" % dhms[1..3] unless dhms[1].zero? return "%d minutes %d seconds" % dhms[2..3] unless dhms[2].zero? "%d seconds" % dhms[3] end


Necesitó un descanso. Golfed esto:

s = 270921 dhms = [60,60,24].reduce([s]) { |m,o| m.unshift(m.shift.divmod(o)).flatten } # => [3, 3, 15, 21]


Puedes usar el método más simple que encontré para este problema:

def formatted_duration total_seconds hours = total_seconds / (60 * 60) minutes = (total_seconds / 60) % 60 seconds = total_seconds % 60 "#{ hours } h #{ minutes } m #{ seconds } s" end

Siempre puede ajustar el valor devuelto a sus necesidades.

2.2.2 :062 > formatted_duration 3661 => "1 h 1 m 1 s"


Rails tiene un helper que convierte la distancia de tiempo en palabras. Puede ver su implementación: distance_of_time_in_words


Si está utilizando Rails, hay una manera fácil de hacerlo si no necesita la precisión:

time_ago_in_words 270921.seconds.from_now # => 3 days


Solo empiezo a escribir Ruby. Supongo que esto es solo para 1.9.3

def dateBeautify(t) cute_date=Array.new tables=[ ["day", 24*60*60], ["hour", 60*60], ["minute", 60], ["sec", 1] ] tables.each do |unit, value| o = t.divmod(value) p_unit = o[0] > 1 ? unit.pluralize : unit cute_date.push("#{o[0]} #{unit}") unless o[0] == 0 t = o[1] end return cute_date.join('', '') end


Se puede hacer de manera muy concisa usando divmod :

t = 270921 mm, ss = t.divmod(60) #=> [4515, 21] hh, mm = mm.divmod(60) #=> [75, 15] dd, hh = hh.divmod(24) #=> [3, 3] puts "%d days, %d hours, %d minutes and %d seconds" % [dd, hh, mm, ss] #=> 3 days, 3 hours, 15 minutes and 21 seconds

Probablemente podrías DIBUJARLO más al ser creativo con la collect , o tal vez inject , pero cuando la lógica central es de tres líneas, puede ser exagerado.