Ruby'de bir DateTime ve bir Time nesnesi arasında nasıl dönüşüm gerçekleştirirsiniz?
Ruby'de bir DateTime ve bir Time nesnesi arasında nasıl dönüşüm gerçekleştirirsiniz?
Yanıtlar:
Biraz farklı iki dönüşüme ihtiyacınız olacak.
Dan dönüştürmek için Time için DateTimeşöyle Zaman sınıfını düzeltebileceksiniz size:
require 'date'
class Time
def to_datetime
# Convert seconds + microseconds into a fractional number of seconds
seconds = sec + Rational(usec, 10**6)
# Convert a UTC offset measured in minutes to one measured in a
# fraction of a day.
offset = Rational(utc_offset, 60 * 60 * 24)
DateTime.new(year, month, day, hour, min, seconds, offset)
end
end
Tarih benzer ayarlamalar dönüştürmek izin verir DateTime etmek Time .
class Date
def to_gm_time
to_time(new_offset, :gm)
end
def to_local_time
to_time(new_offset(DateTime.now.offset-offset), :local)
end
private
def to_time(dest, method)
#Convert a fraction of a day to a number of microseconds
usec = (dest.sec_fraction * 60 * 60 * 24 * (10**6)).to_i
Time.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min,
dest.sec, usec)
end
end
Yerel saat ile GM / UTC saati arasında seçim yapmanız gerektiğini unutmayın.
Yukarıdaki kod parçalarının her ikisi de O'Reilly's Ruby Cookbook'tan alınmıştır . Kod yeniden kullanım politikası buna izin verir.
require 'time'
require 'date'
t = Time.now
d = DateTime.now
dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)
Yakut ekosistemin durumuna bir güncelleme olarak Date, DateTimeve Timeartık çeşitli sınıflar arasındaki dönüştürmek için yöntemler var. Ruby 1.9.2+ kullanımı:
pry
[1] pry(main)> ts = 'Jan 1, 2000 12:01:01'
=> "Jan 1, 2000 12:01:01"
[2] pry(main)> require 'time'
=> true
[3] pry(main)> require 'date'
=> true
[4] pry(main)> ds = Date.parse(ts)
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[5] pry(main)> ds.to_date
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[6] pry(main)> ds.to_datetime
=> #<DateTime: 2000-01-01T00:00:00+00:00 (4903089/2,0,2299161)>
[7] pry(main)> ds.to_time
=> 2000-01-01 00:00:00 -0700
[8] pry(main)> ds.to_time.class
=> Time
[9] pry(main)> ds.to_datetime.class
=> DateTime
[10] pry(main)> ts = Time.parse(ts)
=> 2000-01-01 12:01:01 -0700
[11] pry(main)> ts.class
=> Time
[12] pry(main)> ts.to_date
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[13] pry(main)> ts.to_date.class
=> Date
[14] pry(main)> ts.to_datetime
=> #<DateTime: 2000-01-01T12:01:01-07:00 (211813513261/86400,-7/24,2299161)>
[15] pry(main)> ts.to_datetime.class
=> DateTime
1.9.3p327 :007 > ts = '2000-01-01 12:01:01 -0700' => "2000-01-01 12:01:01 -0700" 1.9.3p327 :009 > dt = ts.to_datetime => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :010 > dt.to_time => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :011 > dt.to_time.class => DateTime
Maalesef DateTime.to_time, Time.to_datetimeve Time.parseişlevleri saat dilimi bilgilerini korumaz. Dönüştürme sırasında her şey yerel saat dilimine dönüştürülür. Tarih aritmetiği hala çalışıyor ancak tarihleri orijinal saat dilimleriyle görüntüleyemeyeceksiniz. Bu bağlam bilgisi genellikle önemlidir. Örneğin, New York'ta iş saatlerinde gerçekleştirilen işlemleri görmek istiyorsam, muhtemelen bunların Avustralya'daki yerel saat dilimimde (New York'tan 12 saat ileride) değil, orijinal saat dilimlerinde görüntülenmesini tercih ederim.
Aşağıdaki dönüştürme yöntemleri bu tz bilgilerini saklar.
Ruby 1.8 için Gordon Wilson'ın cevabına bakın . Eski, güvenilir Ruby Yemek Kitabı'ndan.
Ruby 1.9 için biraz daha kolaydır.
require 'date'
# Create a date in some foreign time zone (middle of the Atlantic)
d = DateTime.new(2010,01,01, 10,00,00, Rational(-2, 24))
puts d
# Convert DateTime to Time, keeping the original timezone
t = Time.new(d.year, d.month, d.day, d.hour, d.min, d.sec, d.zone)
puts t
# Convert Time to DateTime, keeping the original timezone
d = DateTime.new(t.year, t.month, t.day, t.hour, t.min, t.sec, Rational(t.gmt_offset / 3600, 24))
puts d
Bu, aşağıdakileri yazdırır
2010-01-01T10:00:00-02:00
2010-01-01 10:00:00 -0200
2010-01-01T10:00:00-02:00
Saat dilimi dahil tam orijinal DateTime bilgisi saklanır.
Time#to_datetimeTime.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Gordon Wilson çözümünü geliştirmek, işte benim denemem:
def to_time
#Convert a fraction of a day to a number of microseconds
usec = (sec_fraction * 60 * 60 * 24 * (10**6)).to_i
t = Time.gm(year, month, day, hour, min, sec, usec)
t - offset.abs.div(SECONDS_IN_DAY)
end
Saat dilimini kaybederek UTC'de aynı saati alacaksınız (maalesef)
Ayrıca, Ruby 1.9'a sahipseniz, to_timeyöntemi deneyin.
Bu tür dönüşümler yapılırken, bir nesneden diğerine dönüştürülürken saat dilimlerinin davranışı dikkate alınmalıdır. Bu stackoverflow gönderisinde bazı iyi notlar ve örnekler buldum .