Rails 3 또는 Ruby에서 기간을 시간 : 분 : 초 (또는 유사)로 변환


115

이 작업을 수행하는 간단한 / 내장 된 방법이 있다는 느낌이 있지만 찾을 수 없습니다.

정수로 된 기간 (초)이 있고 친숙한 형식으로 표시하고 싶습니다.

예를 들어 3600은 "01:00:00"또는 "1 시간"등으로 표시됩니다.

나는 그것을 할 수 time_ago_in_words(Time.zone.now+3600)있지만 약간의 해킹처럼 느껴집니다.이 값을 포맷하기 위해 현재 시간에서 더하거나 빼야 할 이유가 없습니다. 거기인가 duration_in_words()또는 무엇인가?

감사

답변:


83

참조 : http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html

distance_of_time_in_words(3600)
 => "about 1 hour"

1
고마워요 제가 봤는데 두 번 제공해야한다고 생각 했어요.
cydonia

1
예, 그 예는 어리석은 것입니다
allan

1
distance_of_time_in_words (FROM_TIME, TO_TIME, ...)
boulder_ruby

1
또한 이것이 매우 구체적이고 기간을 "반올림"하지 않으려면 Radar의 gem을 확인하십시오. github.com/radar/distance_of_time_in_words . 드롭 인 교체 distance_of_time_in_wordsvague: true옵션 으로 전달하여 반올림 된 숫자를 얻을 수 있습니다 .
Joshua Pinter는

194

합산:

그것을 가정 total_seconds = 3600

옵션 1:

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

옵션 2 :

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

옵션 3 :

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

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

사용 옵션 1은 당신이 단어를 원하는 경우 옵션 2는 S 형식 : M : 당신은 H 원하는 경우에 옵션 3은 M : 당신이 H 원하는 경우 S 형식을 24 시간 이상이있을 수 있습니다


1
distance_of_time_in_words 메소드는 ActionView Helper이므로 컨트롤러가 아닌 View에서 호출해야합니다. api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html
msdundar

13
strftime 옵션은 24 시간에 오버플로됩니다. 기간이 25 시간이면이 표시됩니다 01:00:00.
Gabe Martin-Dempesy 2015

2
음수 시간에는 작동하지 않습니다. 예를 들어 -1800은 -30m 대신 -1h 30m을 반환합니다.
Arnold Roa

44

Ruby의 문자열 %연산자는 너무 감사하지 않고 자주 잊혀집니다.

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

을 감안할 때 , t는 초 단위 기간입니다,이 일을 포함하여 제로 패딩 콜론으로 구분 된 문자열을 방출한다. 예:

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

아름다운.


24
그것은 "사랑스러운"의 이상한 정의입니다.
Marc Bollinger 2015 년

10
%"내 오른쪽에서 매개 변수의 배열을 가지고 내 왼쪽에 형식 문자열에 삽입"라고 말한다. 그 점 printf에서 C \ C ++에서 와 비슷하지만 더 간결하고 할당에 사용할 수 있습니다. 네, 사랑 스럽습니다. 그리고 강력합니다. 이 웅변을 더 잘 보여주는 예가 있지만 질문에 대답하지 않습니다. 당신의 snark는 감사하지 않습니다, btw.
IAmNaN

26

다음과 같이 할 수도 있습니다.

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

원하는대로 포맷합니다.

BTW, 원래 Time.at () 사용을 생각했지만 Ubuntu의 EPOCH 시간은 Thu Jan 01 01:00:00 +0100 1970이고 예상대로 00:00:00 시간이 아닌 것으로 보입니다.

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

원하는 것보다 1 시간 더 많이줍니다.


아, 여름철 때문에 뭔가 할 수 있을까요?
Cristobal Viedma

7
유일한 문제는 24 시간 이상 시간을 처리하는 경우입니다. 이 경우 시간은 낮은 숫자로 롤백됩니다.
metavida 2011 년

24 시간을 초과하는 경우 % j는 일 수를 제공합니다 (365 일 미만인 경우)
BananaNeil

18

이것을 사용하여 Rails 프로젝트의 기간을 표시합니다.

  1. Integer클래스에 사용자 지정 메서드를 추가합니다 . 당신은라는 새로운 파일을 생성 할 수 있습니다 pretty_duration.rbinitializers폴더를 :

    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_duration프로젝트 어디에서나 전화 하십시오.

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

이 답변은 Lev Lukomsky의 코드를 기반으로합니다.


훌륭하게 일했습니다. 감사합니다.
Donn Felker

13

이것은 모호한 divmod방법을 사용하여 동시에 나누기와 모듈로를 사용하므로 Float초를 올바르게 처리합니다 .

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

사용 Time.utc.strftime시간의 총 수는 경우에만 값 작품 미만 24입니다 :

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

더 큰 값의 경우 잘못된 결과를 반환합니다.

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

이 문제에 대해 찾은 가장 간단한 방법을 사용하는 것이 좋습니다.

  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

반환 값을 언제든지 필요에 맞게 조정할 수 있습니다.


5

하루보다 긴 시간에주의하십시오.

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

강조 입력 / 출력의 예를 들기로 해결할 방법이 코너 케이스
릴 Duchon-도리스

4

ActiveSupport :: Duration을 활용하고 밀리 초를 처리하는 Lev Lukomsky의 답변 (코드 벤치 마크에 유용)

# 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"

물론 관련 ActiveSupport 방법을 사용하고 동일한 구조를 반복하여 일, 월, 년 등으로 쉽게 확장 할 수 있습니다.

너무 긴 기간의 경우 1 개월 기간이 일 수로 고정되어 있지 않기 때문에 이것은 정확하지 않을 수 있으며 AS : Duration이 어떻게 처리하는지 잘 모르겠습니다.


2

2 센트 만 넣으면됩니다.

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

Xiao Bin의 답변을 바탕으로 구축되었습니다.


2

베스트 답변을 제공 한 @joshuapinter 에게 외쳐 주세요 (코멘트 형식 ).

드롭 인 교체 dotiw젬을 사용하여 다양한 요구 사항에 맞게 출력의 정확도를 더 많이 제어 할 수 있습니다.

https://github.com/radar/distance_of_time_in_words

샘플보기 코드 :

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

결과는 다음과 같습니다.

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

2

ActiveSupport::Duration.build+ inspect유효한 결과를 제공합니다

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.