web-dev-qa-db-fra.com

Comment modifier le fuseau horaire d'un DateTime dans Ruby?

Lire, écrire et sérialiser les dates et les heures tout en maintenant le fuseau horaire constant devient ennuyeux. J'utilise Ruby (et Rails 3.0) et j'essaie de modifier le fuseau horaire d'un DateTime. (à UTC) mais pas le temps lui-même.

Je veux ceci:

t = DateTime.now
t.hour
-> 4
t.offset = 0
t.hour
-> 4
t.utc?
-> true

Le plus proche que je suis venu est celui-ci, mais ce n’est pas intuitif.

t = DateTime.now
t.hour
-> 4
t += t.offset
t = t.utc
t.hour
-> 4
t.utc?
-> true

Y a-t-il une meilleure façon?

21
Daniel Beardsley

En utilisant Rails 3, vous recherchez DateTime.change ()

dt = DateTime.now
=> Mon, 20 Dec 2010 18:59:43 +0100
dt = dt.change(:offset => "+0000")
=> Mon, 20 Dec 2010 18:59:43 +0000
35
Alex Kremer

Utilisation d’un décalage numérique, par exemple '+1000' ne fonctionnera pas toute l'année en raison de l'heure avancée. Commander ActiveSupport :: TimeZone. Plus d'infos ici

9
Sam
d = DateTime.now
puts [ d, d.zone ]
#=> 2010-12-17T13:28:29-07:00
#=> -07:00

d2 = d.new_offset(3.0/24)
puts d2, d2.zone
#=> 2010-12-17T23:28:29+03:00
#=> +03:00

Éditer : Cette réponse ne prend pas en compte les informations fournies par un commentaire à une autre réponse indiquant que vous souhaitez que les "heures" signalées soient identiques après le changement de fuseau horaire.

8
Phrogz

Je voudrais utiliser un Time object à la place. Obtenez donc l'heure locale actuelle, puis incrémentez-la de l'offset UTC et convertissez-la en UTC, comme suit:

t = Time.now # or Time.parse(myDateTime.asctime)
t # => Thu Dec 16 21:07:48 -0800 2010
(t + t.utc_offset).utc # => Thu Dec 16 21:07:48 UTC 2010

Selon Phrogz, si vous voulez simplement stocker les horodatages de manière indépendante de l'emplacement, utilisez simplement l'heure UTC actuelle:

Time.now.utc
8
maerics

Comme l'a souligné @Sam , la modification du décalage n'est pas suffisante et entraînerait des erreurs. Pour résister aux avancées de l'horloge DST, la conversion doit s'effectuer de la manière suivante:

d = datetime_to_alter_time_zone
time_zone = 'Alaska'

DateTime.new
  .in_time_zone(time_zone)
  .change(year: d.year, month: d.month, day: d.day, hour: d.hour, min: d.min, sec: d.sec)
3
kogitoja

Si quelqu'un (comme moi) a le fuseau horaire en format de chaîne du type "Heure du Pacifique (États-Unis et Canada)"

Alors c'est la meilleure façon que j'ai trouvée:

datetime.change(ActiveSupport::TimeZone[time_zone_string].formatted_offset(false)
1
Zia Ul Rehman Mughal