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.