Câu trả lời:
DateTime.strptime
có thể xử lý giây kể từ kỷ nguyên. Số phải được chuyển đổi thành một chuỗi:
require 'date'
DateTime.strptime("1318996912",'%s')
%Q
tho.
Time
là cần thiết thay vì DateTime
. Vì vậy, sử dụng Time.strptime("1318996912345",'%Q').to_f
và bạn sẽ thấy một phần nghìn giây được bảo tồn, trong khi DateTime.strptime("1318996912345",'%Q').to_f
không bảo tồn nó.
Xin lỗi, khoảnh khắc ngắn gọn của sự thất bại synapse. Đây là câu trả lời thực sự.
require 'date'
Time.at(seconds_since_epoch_integer).to_datetime
Ví dụ ngắn gọn (điều này tính đến múi giờ hệ thống hiện tại):
$ 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)>
Cập nhật thêm (cho 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)>
Cập nhật gần đây : Tôi đã điểm chuẩn các giải pháp hàng đầu trong chuỗi này khi làm việc trên dịch vụ HA một hoặc hai tuần trước và rất ngạc nhiên khi thấy rằng nó Time.at(..)
vượt trội hơn DateTime.strptime(..)
(cập nhật: thêm nhiều điểm chuẩn).
# ~ % 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>
Time.at
vượt trội hơn DateTime.strptime
. Cái sau phải phân tích một chuỗi, thường chậm hơn nhiều so với lấy trực tiếp một số.
DateTime.strptime
vì nó tạo ra hai Chuỗi mới mỗi lần lặp rất tốn kém. Đó không chỉ là phân tích cú pháp chuỗi như @claw đã nói
Xử lý múi giờ
Tôi chỉ muốn làm rõ, mặc dù điều này đã được bình luận để mọi người trong tương lai không bỏ lỡ sự khác biệt rất quan trọng này.
DateTime.strptime("1318996912",'%s') # => Wed, 19 Oct 2011 04:01:52 +0000
hiển thị giá trị trả về trong UTC và yêu cầu giây phải là Chuỗi và xuất ra đối tượng Thời gian UTC, trong khi
Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
hiển thị giá trị trả về trong múi giờ ĐỊA PHƯƠNG, thông thường yêu cầu đối số FixNum, nhưng bản thân đối tượng Thời gian vẫn ở trong UTC mặc dù màn hình không hiển thị.
Vì vậy, mặc dù tôi đã truyền cùng một số nguyên cho cả hai phương thức, tôi dường như có hai kết quả khác nhau do cách #to_s
thức hoạt động của phương thức lớp . Tuy nhiên, như @Eero đã phải nhắc tôi hai lần:
Time.at(1318996912) == DateTime.strptime("1318996912",'%s') # => true
Một so sánh bằng giữa hai giá trị trả về vẫn trả về true. Một lần nữa, điều này là do các giá trị về cơ bản là giống nhau (mặc dù các lớp khác nhau, #==
phương thức này đảm nhận việc này cho bạn), nhưng #to_s
phương thức in các chuỗi khác nhau mạnh mẽ. Mặc dù, nếu chúng ta nhìn vào các chuỗi, chúng ta có thể thấy chúng thực sự giống nhau, chỉ được in ở các múi giờ khác nhau.
Phương pháp làm rõ đối số
Các tài liệu cũng nói "Nếu một đối số số được đưa ra, kết quả là theo giờ địa phương." điều này có ý nghĩa, nhưng hơi khó hiểu với tôi vì họ không đưa ra bất kỳ ví dụ nào về các đối số không nguyên trong tài liệu. Vì vậy, đối với một số ví dụ đối số không nguyên:
Time.at("1318996912")
TypeError: can't convert String into an exact number
bạn không thể sử dụng đối số Chuỗi, nhưng bạn có thể sử dụng đối số Thời gian Time.at
và nó sẽ trả về kết quả trong múi giờ của đối số:
Time.at(Time.new(2007,11,1,15,25,0, "+09:00"))
=> 2007-11-01 15:25:00 +0900
Điểm chuẩn
Sau một cuộc thảo luận với @AdamEberlin về câu trả lời của anh ấy, tôi quyết định công bố điểm chuẩn thay đổi một chút để mọi thứ đều bình đẳng nhất có thể. Ngoài ra, tôi không bao giờ muốn phải xây dựng lại những thứ này vì vậy đây là nơi tốt nhất để cứu chúng.
Time.at (int) .to_datetime ~ 2.8x nhanh hơn
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>
**** được chỉnh sửa để không hoàn toàn và hoàn toàn không chính xác theo mọi cách ****
**** thêm điểm chuẩn ****
Time.at(1318996912) == DateTime.strptime("1318996912",'%s')
trong múi giờ không thuộc UTC và bạn sẽ thấy!
Time.use_zone "Samoa" do Time.at(1318996912) == DateTime.strptime("1318996912",'%s') end
để xác minh rằng thời gian bằng nhau, không có dấu thời gian ĐỊA PHƯƠNG và trong cả hai trường hợp, dấu thời gian Unix được hiểu là ở trong UTC. Time.at
trình bày đối tượng Thời gian kết quả theo múi giờ địa phương và DateTime.strptime
trình bày đối tượng DateTime kết quả trong UTC, nhưng bất kể trình bày chúng có bằng nhau, vì chúng là thời điểm tương đương theo thời gian.
Time.at(1318996912) # => 2011-10-19 00:01:52 -0400
hiển thị giá trị trả về trong múi giờ ĐỊA PHƯƠNG có vẻ không chính xác ... Bạn có thể xác minh không? Tôi tin rằng tuyên bố của bạn sẽ chỉ đúng nếu bạn sử dụngTime.zone.at(1318996912)
Một lệnh để chuyển đổi thời gian ngày sang định dạng Unix và sau đó thành chuỗi
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
cuối cùng strftime được sử dụng để định dạng ngày
Thí dụ:
irb(main):034:0> DateTime.strptime("1410321600",'%s').strftime("%d %m %y")
"10 09 14"
Time.now.utc.to_i
.
Điều này cho bạn biết ngày của số giây trong tương lai kể từ thời điểm bạn thực thi mã.
time = Time.new + 1000000000 #date in 1 billion seconds
đặt (thời gian)
theo thời điểm hiện tại tôi đang trả lời câu hỏi mà nó in ra 047-05-14 05:16:16 +0000
(1 tỷ giây trong tương lai)
hoặc nếu bạn muốn đếm hàng tỷ giây từ một thời điểm cụ thể, thì đó là định dạng Time.mktime(year, month,date,hours,minutes)
time = Time.mktime(1987,8,18,6,45) + 1000000000
đặt ("Tôi sẽ là 1 tỷ giây tuổi:" + thời gian)