web-dev-qa-db-fra.com

Convertir vers / à partir de l’heure et de la date en Ruby

Comment convertir un objet DateTime et Time en Ruby?

129
Readonly

Vous aurez besoin de deux conversions légèrement différentes.

Pour convertir de Time à DateTime, vous pouvez modifier la classe Time comme suit:

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

Des ajustements similaires à Date vous permettront de convertir DateTime en 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

Notez que vous devez choisir entre l'heure locale et l'heure GM/UTC.

Les deux extraits de code ci-dessus proviennent de O'Reilly Ruby Cookbook . Leur réutilisation de code politique le permet.

48
Gordon Wilson
require 'time'
require 'date'

t = Time.now
d = DateTime.now

dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)
180
anshul

En tant que mise à jour de l'état de l'écosystème Ruby, Date, DateTime et Time, il existe maintenant des méthodes de conversion entre les différentes classes. Utilisation de Ruby 1.9.2+:

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
61
the Tin Man

Malheureusement, les fonctions DateTime.to_time, Time.to_datetime Et Time.parse Ne conservent pas les informations de fuseau horaire. Tout est converti en fuseau horaire local lors de la conversion. L'arithmétique des dates fonctionne toujours, mais vous ne pourrez pas afficher les dates avec leurs fuseaux horaires d'origine. Cette information de contexte est souvent importante. Par exemple, si je souhaite voir des transactions effectuées pendant les heures de bureau à New York, je préfère probablement les voir affichées dans leur fuseau horaire d'origine, et non dans mon fuseau horaire local en Australie (qui compte 12 heures d'avance sur New York).

Les méthodes de conversion ci-dessous conservent cette information tz.

Pour Ruby 1.8, regardez réponse de Gordon Wilson . C'est du bon vieux fiable Ruby Cookbook.

Pour Ruby 1.9, c'est légèrement plus facile.

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

Ceci imprime ce qui suit

2010-01-01T10:00:00-02:00
2010-01-01 10:00:00 -0200
2010-01-01T10:00:00-02:00

Les informations DateTime d'origine complètes, y compris le fuseau horaire, sont conservées.

10
Bernard

Pour améliorer la solution Gordon Wilson, voici mon essai:

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

Vous obtiendrez le même temps en UTC, en perdant le fuseau horaire (malheureusement)

En outre, si vous avez Ruby 1.9, essayez simplement le to_time méthode

1
Mildred