it-swarm.dev

bagaimana mengkonversi 270921sec menjadi hari + jam + menit + dtk (Rubi)

Saya punya beberapa detik. Katakanlah 270921. Bagaimana saya bisa menampilkan angka yang mengatakan itu xx hari, yy jam, zz menit, ww detik?

60
Radek

Ini dapat dilakukan dengan cukup singkat menggunakan 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

Anda mungkin bisa DRY lebih jauh dengan menjadi kreatif dengan collect, atau mungkin inject, tetapi ketika logika intinya adalah tiga baris, itu mungkin berlebihan.

146
Mike Woodhouse

Saya berharap akan ada cara yang lebih mudah daripada menggunakan divmod, tapi ini adalah yang paling DRY dan cara yang dapat digunakan kembali yang saya temukan untuk melakukannya:

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

Metode ini mudah disesuaikan dengan mengubah format string dan array inline pertama (yaitu [24,60,60]).

Versi yang ditingkatkan

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

Contoh:

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"

Perhatikan bahwa format_string tidak akan membiarkan Anda mengubah urutan bagian-bagian (itu selalu nilai paling signifikan untuk paling sedikit). Untuk kontrol berbutir halus, Anda dapat menggunakan split dan memanipulasi nilai sendiri.

13
Kelvin

Perlu istirahat. Dikutip dari sini:

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

Rails memiliki penolong yang mengubah jarak waktu dalam kata-kata . Anda dapat melihat implementasinya: distance_of_time_in_words

9
Simone Carletti

Jika Anda menggunakan Rails, ada cara mudah jika Anda tidak membutuhkan ketelitian:

time_ago_in_words 270921.seconds.from_now
# => 3 days
9
adamlamar

Anda dapat menggunakan metode paling sederhana yang saya temukan untuk masalah ini:

  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

Anda selalu dapat menyesuaikan nilai yang dikembalikan dengan kebutuhan Anda.

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

Saya baru saja mulai menulis Ruby. Saya kira ini hanya untuk 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
2
patai

Saya memodifikasi jawaban yang diberikan oleh @Mike untuk menambahkan pemformatan dinamis berdasarkan ukuran hasilnya 

      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
0
SMAG