Süreyi saate çevirin: dakika: saniye (veya benzeri) Rails 3 veya Ruby'de


115

Bunu yapmanın basit / yerleşik bir yolu olduğunu hissediyorum ama bulamıyorum.

Tamsayıda bir sürem var (saniye cinsinden) ve bunu kolay bir biçimde görüntülemek istiyorum.

örneğin 3600, "01:00:00" veya "1 saat" veya başka bir şekilde görüntülenecektir.

Bununla yapabilirim time_ago_in_words(Time.zone.now+3600)ama bu biraz hack gibi geliyor, sadece bu değeri biçimlendirmek için şimdiki zamandan ekleme / çıkarma yapmak için hiçbir neden yok. Bir duration_in_words()şey mi var ?

Teşekkürler

Yanıtlar:


83

Bakınız: http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html

distance_of_time_in_words(3600)
 => "about 1 hour"

1
teşekkürler, ona baktım ama iki kez sağlamam gerektiğini düşündüm .. ne bir nub!
cydonia

1
evet, bu örnekler saçma
allan

1
distance_of_time_in_words (from_time, to_time, ...)
boulder_ruby

1
Ayrıca, bunun çok spesifik olmasını ve süreyi "yuvarlamamasını" istiyorsanız, Radar'ın mücevherine bakın: github.com/radar/distance_of_time_in_words . Drop-in yerine distance_of_time_in_wordsgeçebilir vague: trueve bir seçenek olarak geçerek yuvarlanmış sayıyı alabilirsiniz .
Joshua Pinter

194

Özetliyor:

varsayarsak total_seconds = 3600

Seçenek 1:

distance_of_time_in_words(total_seconds) #=> "about 1 hour"

Seçenek 2:

Time.at(total_seconds).utc.strftime("%H:%M:%S") #=> "01:00:00"

3. Seçenek:

seconds = total_seconds % 60
minutes = (total_seconds / 60) % 60
hours = total_seconds / (60 * 60)

format("%02d:%02d:%02d", hours, minutes, seconds) #=> "01:00:00"

kullanım Seçim1 , kelimeleri istiyorsanız 2. seçenek S biçimi,: M: Eğer H istiyorsanız 3. seçenek M: Eğer H istiyorsanız S biçimini ve 24 saatten fazla olamaz


1
Distance_of_time_in_words yöntemi bir ActionView Yardımcısıdır, bu nedenle Görünümden (denetleyiciden değil) çağrılması gerekir. api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html
msdundar

13
Strftime seçeneğinin 24 saatte dolacağını unutmayın. Süreniz 25 saat ise görüntülenecektir 01:00:00.
Gabe Martin-Dempesy

2
bu, negatif zamanlarda işe yaramaz, örneğin -1800, -30m yerine -1h 30m döndürür
Arnold Roa

45

Ruby'nin dizgi %operatörü çok takdir edilmemiştir ve çoğu zaman unutulmuştur.

"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]

T saniye cinsinden bir süre olarak verildiğinde , bu, günler de dahil olmak üzere sıfır dolgulu iki nokta üst üste ile ayrılmış bir dize yayar. Misal:

t = 123456
"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]
=> "01:10:17:36"

Güzel.


24
Bu "sevimli" nin garip bir tanımı.
Marc Bollinger

10
%"Benim sağdan parametrelerin dizi alın ve benim soldaki biçim dizesi içine yerleştirin." Diyor Bu açıdan, printfC \ C ++ 'ya benzer, sadece daha özlüdür ve bir atamada kullanılabilir. Evet, buna sevimli diyorum. Ve güçlü. Bu belagatı daha iyi gösterecek örnekler var, ancak soruyu cevaplamıyorlar. Hırçınlığınız takdir edilmiyor, btw.
IAmNaN

26

Sanırım şunun gibi bir şey de yapabilirsiniz:

(Time.mktime(0)+3600).strftime("%H:%M:%S")

İstediğiniz gibi biçimlendirmek için.

BTW, başlangıçta Time.at () kullanmayı düşündüm ancak Ubuntu'mdaki EPOCH zamanının 01 Ocak 01:00:00 +0100 1970 ve beklediğim gibi 00:00:00 saat değil gibi görünüyor ve bu nedenle yaparsam:

Time.at(3600).strftime("%H:%M:%S")

Bana istenenden 1 saat daha fazlasını veriyor.


ahh, yaz saati nedeniyle yapacak bir şey olabilir mi?
Cristobal Viedma

7
Tek sorun, 24 saatten fazla zamanla uğraşıyorsanız. Bu durumda saatler düşük bir sayıya geri dönecektir.
metavida

24 saatten uzun süreler için,% j size gün sayısını verecektir (
365'ten

18

Bunu Rails Projemde zaman sürelerini göstermek için kullanıyorum:

  1. IntegerSınıfa özel bir yöntem ekleyin . Sen adlı yeni bir dosya oluşturabilirsiniz pretty_duration.rbiçinde initializersklasörün:

    class Integer
        def pretty_duration
            parse_string = 
                if self < 3600
                    '%M:%S'
                else
                    '%H:%M:%S'
                end
    
            Time.at(self).utc.strftime(parse_string)
        end
    end
  2. seconds.pretty_durationProjenizdeki herhangi bir yeri arayın :

    275.pretty_duration     # => "04:35"
    9823.pretty_duration    # => "02:43:43"

Bu cevap, Lev Lukomsky'nin Kurallarına dayanmaktadır.


Harika çalıştı. Bunun için teşekkür ederim.
Donn Felker

13

Bu divmod, aynı anda bölmek ve modulo yapmak için belirsiz yöntemi kullanır , böylece Floatsaniyeleri doğru şekilde işler :

def duration(seconds)
  minutes, seconds = seconds.divmod(60)
  hours, minutes = minutes.divmod(60)
  days, hours = hours.divmod(24)

  "#{days.to_s.rjust(3)}d #{hours.to_s.rjust(2)}h #{minutes.to_s.rjust(2)}m #{seconds}s"
end

6

Kullanılması Time.utc.strftimesaat toplam sayısı yalnızca değerler için çalışmalarını az sonra 24 olduğu :

2.2.2 :004 > Time.at(60 * 60).utc.strftime('%H h %M m')
=> "01 h 00 m"

Daha büyük değerler için yanlış sonuçlar verir:

2.2.2 :006 > Time.at(60 * 60 * 24).utc.strftime('%H h %M m')
 => "00 h 00 m"

Bu sorun için bulduğum en basit yöntemi kullanmanızı öneririm:

  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

İade edilen değeri her zaman ihtiyaçlarınıza göre ayarlayabilirsiniz.


5

Bir günden uzun süreye dikkat edin.

(timing/3600).to_i.to_s.rjust(2,'0') + ":"+Time.at(timing).utc.strftime("%M:%S")

Bunun köşe vakasını nasıl çözdüğünü vurgulayan bir girdi / çıktı örneği verin
Cyril Duchon-Doris

4

Lev Lukomsky'nin ActiveSupport :: Süre'den yararlanan ve milisaniyeleri işleyen sorusundan ilham alan bir cevap (kodu karşılaştırmak için kullanışlıdır)

# duration in ms modulus number of ms in one second
milliseconds = duration.in_milliseconds % 1.second.in_milliseconds

# duration in seconds modulus number of seconds in one minute
seconds = (duration / 1.second) % (1.minute / 1.second)

# duration in minutes modulus number of minutes in one hour
minutes = (duration / 1.minute) % (1.hour / 1.minute)

# duration in hours modulus number of hours in one day
hours = (duration / 1.hour) % (1.day / 1.hour)

format("%02d:%02d:%02d:%03d", hours, minutes, seconds, milliseconds) #=> "12:05:00:001"

Elbette bunu ilgili ActiveSupport yöntemlerini kullanarak ve aynı yapıyı tekrarlayarak günler, aylar, yıllar vb. İle kolayca uzatabilirsiniz.

Çok uzun süreler için, 1 aylık süre gün sayısı olarak sabit olmadığından bunun yanlış olabileceğini ve AS: Duration bununla nasıl ilgilendiğinden emin değilim.


2

Sadece 2 sentimi atmak için:

Time.at(i).utc.strftime((i < 3600) ? '%-M minutes and %-S seconds' : '%-H hours, %-M minutes, and %-S seconds')

Xiao Bin'in cevabından oluşturuldu.


2

Haykıracağım @joshuapinter şeklinde (En iyi yanıtı veren bir yorumun ).

dotiwFarklı ihtiyaçlara uyacak şekilde çıktının doğruluğu üzerinde daha fazla kontrol elde etmek için drop-in yedek mücevherini kullanın:

https://github.com/radar/distance_of_time_in_words

Örnek görünüm kodu:

%label
  Logoff after:
  - expire_in = distance_of_time_in_words(Time.now, Time.now + user.custom_timeout.minutes, :only => [:minutes, :hours, :days])
  = expire_in

Bunun gibi bir sonuçla:

Logoff after: 1 day, 13 hours, and 20 minutes

2

ActiveSupport::Duration.build+ inspectsize geçerli sonuçlar verir

 >> ActiveSupport::Duration.build(125557).inspect
 => "1 day, 10 hours, 52 minutes, and 37 seconds"

1
    hours = 3.5456
    value = (hours*60).divmod(60).map{ |a| "%02d"%[a.floor] }.join(":")
    => "03:32"

5
Lütfen yanıta biraz bağlam ekleyin.
Paul Dawson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.