유닉스 타임 스탬프 (epoch 이후 초)를 Ruby DateTime으로 변환하는 방법은 무엇입니까?


답변:


354

DateTime.strptime에포크 이후 초를 처리 할 수 ​​있습니다. 숫자는 문자열로 변환되어야합니다.

require 'date'
DateTime.strptime("1318996912",'%s')

4
이것은 소수의 초를 처리하지 않습니다
Dan Sandberg

45
%Qtho로 밀리 초를 처리 합니다.
미니 존

3
@TheMiniJohn의 답변에 대한 후속 조치. Time대신에 필요한 것 같습니다 DateTime. 따라서 사용 Time.strptime("1318996912345",'%Q').to_f하면 밀리 초는 유지되지만 밀리 초는 유지 DateTime.strptime("1318996912345",'%Q').to_f되지 않습니다.
skensell

625

죄송합니다. 짧은 시냅스 장애 순간입니다. 실제 답변은 다음과 같습니다.

require 'date'

Time.at(seconds_since_epoch_integer).to_datetime

간단한 예 (현재 시스템 시간대를 고려함) :

$ date +%s
1318996912

$ irb

ruby-1.9.2-p180 :001 > require 'date'
 => true 

ruby-1.9.2-p180 :002 > Time.at(1318996912).to_datetime
 => #<DateTime: 2011-10-18T23:01:52-05:00 (13261609807/5400,-5/24,2299161)> 

추가 업데이트 (UTC의 경우) :

ruby-1.9.2-p180 :003 > Time.at(1318996912).utc.to_datetime
 => #<DateTime: 2011-10-19T04:01:52+00:00 (13261609807/5400,0/1,2299161)>

최근 업데이트 : 일주일 또는 이틀 전에 HA 서비스를 작업 하면서이 스레드에서 최고의 솔루션을 벤치마킹했으며 Time.at(..)성능 이 뛰어남 DateTime.strptime(..)(업데이트 : 더 많은 벤치 마크 추가) 에 놀랐습니다 .

# ~ % ruby -v
#  => ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin13.0]

irb(main):038:0> Benchmark.measure do
irb(main):039:1*   ["1318996912", "1318496912"].each do |s|
irb(main):040:2*     DateTime.strptime(s, '%s')
irb(main):041:2>   end
irb(main):042:1> end

=> #<Benchmark ... @real=2.9e-05 ... @total=0.0>

irb(main):044:0> Benchmark.measure do
irb(main):045:1>   [1318996912, 1318496912].each do |i|
irb(main):046:2>     DateTime.strptime(i.to_s, '%s')
irb(main):047:2>   end
irb(main):048:1> end

=> #<Benchmark ... @real=2.0e-05 ... @total=0.0>

irb(main):050:0* Benchmark.measure do
irb(main):051:1*   ["1318996912", "1318496912"].each do |s|
irb(main):052:2*     Time.at(s.to_i).to_datetime
irb(main):053:2>   end
irb(main):054:1> end

=> #<Benchmark ... @real=1.5e-05 ... @total=0.0>

irb(main):056:0* Benchmark.measure do
irb(main):057:1*   [1318996912, 1318496912].each do |i|
irb(main):058:2*     Time.at(i).to_datetime
irb(main):059:2>   end
irb(main):060:1> end

=> #<Benchmark ... @real=2.0e-05 ... @total=0.0>

1
감사합니다 ... 다음 답변은 좀 더 간결합니다 .Time.at를 찾았지만 DateTime에 해당하는 것을 찾으려고했습니다.
Tronathan

27
재밌지 만 Time.at (). to_datetime은 가독성 때문에 DateTime.strptime ()보다 더 즐거워 보입니다 ... 적어도 어쨌든
tybro0103

34
이것은 위의 anser와 동일하지 않습니다. Time.at은 현재 시간대를 가정합니다. 여기서 DateTime.strptime은 UTC를 사용합니다.
Vitaly Babiy

5
Time.at성능 이 뛰어나다는 것은 놀라운 일이 아닙니다 DateTime.strptime. 후자는 문자열을 파싱해야하는데, 이는 일반적으로 숫자를 직접받는 것보다 훨씬 느립니다.
Claw

2
벤치 마크는 DateTime.strptime매번 반복 할 때마다 두 개의 새로운 문자열을 생성하기 때문에 정확하게 테스트되지 않습니다 . 그것은하지 그냥 @claw 같은 구문 분석 문자열 말했다
WattsInABox

67

시간대 처리

미래의 사람들 이이 중요한 차이점을 놓치지 않도록 주석을 달았지만 명확히하고 싶습니다.

DateTime.strptime("1318996912",'%s') # => Wed, 19 Oct 2011 04:01:52 +0000

UTC로 반환 값을 표시하고 초는 String이어야하고 UTC Time 객체를 출력합니다.

Time.at(1318996912) # => 2011-10-19 00:01:52 -0400

LOCAL 표준 시간대에 반환 값을 표시하며 일반적으로 FixNum 인수가 필요하지만 표시가 아닌 경우에도 Time 개체 자체는 여전히 UTC입니다.

따라서 두 정수에 동일한 정수를 전달했지만 클래스의 방법으로 인해 두 가지 다른 결과가 나타납니다. #to_s 메소드 작동 방식으로 가 나타납니다. 그러나 @Eero는 나에게 두 번 상기시켜야했습니다.

Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true

두 반환 값 사이의 동등 비교는 여전히 true를 반환합니다. 다시 말하지만 이는 기본적으로 값이 동일하기 때문입니다 (다른 클래스에도 불구하고#== 메소드가이를 처리하지만) #to_s메소드는 크게 다른 문자열을 인쇄합니다. 문자열을 보면 실제로 다른 시간대에 인쇄 된 문자열이 실제로 같은 시간임을 알 수 있습니다.

메소드 인수 설명

문서는 또한 "숫자 인수가 주어지면 결과는 현지 시간입니다"라고 말합니다. 이것은 말이되지만 문서에 정수가 아닌 인수의 예를 제공하지 않기 때문에 약간 혼란 스럽습니다. 따라서 정수가 아닌 인수 예제의 경우 :

Time.at("1318996912")
TypeError: can't convert String into an exact number

String 인수를 사용할 수 없지만 Time 인수를 사용할 수 Time.at있으며 인수의 시간대에 결과를 반환합니다.

Time.at(Time.new(2007,11,1,15,25,0, "+09:00"))
=> 2007-11-01 15:25:00 +0900

벤치 마크

그의 답변에 대한 @AdamEberlin과의 토론 후, 나는 모든 것을 가능한 동일하게 만들기 위해 약간 변경된 벤치 마크를 게시하기로 결정했습니다. 또한, 나는 이것을 다시 구축하고 싶지 않으므로 이것을 저장하기에 좋은 곳입니다.

Time.at (int) .to_datetime ~ 2.8x 빠름

09:10:58-watsw018:~$ ruby -v
ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]
09:11:00-watsw018:~$ irb
irb(main):001:0> require 'benchmark'
=> true
irb(main):002:0> require 'date'
=> true
irb(main):003:0>
irb(main):004:0* format = '%s'
=> "%s"
irb(main):005:0> times = ['1318996912', '1318496913']
=> ["1318996912", "1318496913"]
irb(main):006:0> int_times = times.map(&:to_i)
=> [1318996912, 1318496913]
irb(main):007:0>
irb(main):008:0* datetime_from_strptime = DateTime.strptime(times.first, format)
=> #<DateTime: 2011-10-19T04:01:52+00:00 ((2455854j,14512s,0n),+0s,2299161j)>
irb(main):009:0> datetime_from_time = Time.at(int_times.first).to_datetime
=> #<DateTime: 2011-10-19T00:01:52-04:00 ((2455854j,14512s,0n),-14400s,2299161j)>
irb(main):010:0>
irb(main):011:0* datetime_from_strptime === datetime_from_time
=> true
irb(main):012:0>
irb(main):013:0* Benchmark.measure do
irb(main):014:1*   100_000.times {
irb(main):015:2*     times.each do |i|
irb(main):016:3*       DateTime.strptime(i, format)
irb(main):017:3>     end
irb(main):018:2>   }
irb(main):019:1> end
=> #<Benchmark::Tms:0x00007fbdc18f0d28 @label="", @real=0.8680500000045868, @cstime=0.0, @cutime=0.0, @stime=0.009999999999999998, @utime=0.86, @total=0.87>
irb(main):020:0>
irb(main):021:0* Benchmark.measure do
irb(main):022:1*   100_000.times {
irb(main):023:2*     int_times.each do |i|
irb(main):024:3*       Time.at(i).to_datetime
irb(main):025:3>     end
irb(main):026:2>   }
irb(main):027:1> end
=> #<Benchmark::Tms:0x00007fbdc3108be0 @label="", @real=0.33059399999910966, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.32000000000000006, @total=0.32000000000000006>

**** 모든면에서 완전하고 완전하게 부정확하지 않도록 편집 ****

**** 추가 된 벤치 마크 ****


3
그럴듯 해 보였고 이미 찬성했지만 (현재 철회 할 수는 없지만) UTC에 대한 귀하의 주장을 자세히 확인한 결과는 사실이 아닙니다. 결과 DateTime / Time 객체는 UTC와 로컬로 표시되지만 원래 타임 스탬프는 두 경우 모두 UTC로 해석됩니다! 따라서 시간의 순간은 방법에 관계없이 동일합니다. Time.at(1318996912) == DateTime.strptime("1318996912",'%s')비 UTC 시간대로 시도 하면 볼 수 있습니다!
Eero

4
죄송 합니다만, 정정하신 내용은 여전히 ​​틀 렸습니다! :-) Time.use_zone "Samoa" do Time.at(1318996912) == DateTime.strptime("1318996912",'%s') end시간이 동일한 지, LOCAL 타임 스탬프가 없는지 확인하고 두 경우 모두 Unix 타임 스탬프가 UTC로 해석됩니다. Time.at 선물 로컬 시간대에서 얻어진 시차 객체 및 DateTime.strptime 선물 들이 시간에 해당하는 순간만큼 UTC 날짜 시간에 생성 된 객체를 있지만 관계없이 프레젠테이션 이들은 동일하다.
Eero

반면 Time.at(1318996912) # => 2011-10-19 00:01:52 -0400지역 시간대의 반환 값이 표시 정확하게 표시되지 않습니다 ... 당신이 확인시겠습니까? 난 당신이 사용하는 경우 문은 사실이 될 것이라고 생각Time.zone.at(1318996912)
BigRon

예, 정확 해 보입니다. 로컬 컴퓨터가 EST로 설정되고 시간이 EST로 표시됩니다.
WattsInABox 15시 59 분

이것이 @BigRon이 아닌 예를 제공 할 수 있습니까? 어떤 시간대, 루비 버전 등이 이런 식으로 작동하지 않습니까?
WattsInABox

10

날짜 시간을 Unix 형식으로 변환 한 다음 문자열로 변환하는 하나의 명령

    DateTime.strptime(Time.now.utc.to_i.to_s,'%s').strftime("%d %m %y")

    Time.now.utc.to_i #Converts time from Unix format
    DateTime.strptime(Time.now.utc.to_i.to_s,'%s') #Converts date and time from unix format to DateTime

마지막으로 strftime은 날짜 형식을 지정하는 데 사용됩니다

예:

    irb(main):034:0> DateTime.strptime("1410321600",'%s').strftime("%d %m %y")
    "10 09 14"

한 가지 주목할 점은 에포크 형식에는 시간대가 없으므로 to_i를 연결하기 전에 utc를 연결하는 것이 필요하지 않다는 것입니다 Time.now.utc.to_i.
Trevor McCasland

1

이것은 코드를 실행하는 순간부터 미래의 초 수를 나타냅니다.

time = Time.new + 1000000000 #date in 1 billion seconds

풋 (시간)

현재 시간에 따라 인쇄 된 질문에 답하고 있습니다 047-05-14 05:16:16 +0000(앞으로 10 억 초)

또는 특정 시간에서 수십억 초를 세고 싶다면 형식입니다. Time.mktime(year, month,date,hours,minutes)

time = Time.mktime(1987,8,18,6,45) + 1000000000

puts ( "10 억 초가되었습니다 :"+ 시간)


0

당신은 단지 날짜를 원한다면, 당신은 할 수있는 Date.strptime(invoice.date.to_s, '%s')invoice.date의 형태로 제공 Fixnum한 후 변환 String.


3
Time.at(1500923406).to_date.to_s=>"2017-07-24"
Chloe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.