70 votes

Comment convertir 270921sec en jours + heures + minutes + s? (rubis)

J'ai quelques secondes. Disons 270921. Comment puis-je afficher ce nombre en indiquant xx jours, aa heures, zz minutes, secondes?

163voto

Mike Woodhouse Points 27748

Cela peut être fait de manière assez concise en utilisant 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
 

Vous pourriez probablement le sécher davantage en faisant preuve de créativité avec collect , ou peut-être inject , mais lorsque la logique de base est constituée de trois lignes, il peut être excessif.

13voto

Kelvin Points 5810

J'espérais qu'il y aurait un moyen plus simple que d'utiliser divmod, mais c'est le plus SEC et réutilisables façon que j'ai trouvée pour le faire:

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

La méthode est facilement ajustée en changeant la chaîne de format et la première inline array (c'est à dire le [24,60,60]).

Version améliorée

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

Exemples:

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"

Notez que format_string ne vous laisseront pas de changer l'ordre des parties (c'est toujours la plus importante de la valeur à tout le moins). Pour un contrôle précis, vous pouvez utiliser split et de manipuler les valeurs vous-même.

12voto

Simone Carletti Points 77653

Rails a un assistant qui convertit la distance de temps en mots. Vous pouvez regarder son implémentation: distance_de_temps_en_words

12voto

Mike Points 51

Besoin d'une pause. Golfé cette place:

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

9voto

adamonduty Points 1202

Si vous utilisez Rails, il existe un moyen simple de ne pas avoir besoin de précision:

 time_ago_in_words 270921.seconds.from_now
# => 3 days
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X