135 votes

Ruby / Rails - Changer le fuseau horaire d'une heure, sans en modifier la valeur

J'ai un dossier foo dans la base de données qui a :start_time y :timezone attributs.

Le site :start_time est une heure en UTC - 2001-01-01 14:20:00 par exemple. Le site :timezone est une chaîne de caractères - America/New_York par exemple.

Je veux créer un nouvel objet Time avec la valeur de :start_time mais dont le fuseau horaire est spécifié par :timezone . Je ne veux pas charger le :start_time et ensuite convertir en :timezone car Rails sera intelligent et mettra à jour l'heure à partir de l'UTC pour qu'elle soit cohérente avec ce fuseau horaire.

Actuellement,

t = foo.start_time
=> 2000-01-01 14:20:00 UTC
t.zone
=> "UTC"
t.in_time_zone("America/New_York")
=> Sat, 01 Jan 2000 09:20:00 EST -05:00

A la place, je veux voir

=> Sat, 01 Jan 2000 14:20:00 EST -05:00

ie. Je veux le faire :

t
=> 2000-01-01 14:20:00 UTC
t.zone = "America/New_York"
=> "America/New_York"
t
=> 2000-01-01 14:20:00 EST

87voto

Frederick Cheung Points 38410

On dirait que vous voulez quelque chose du genre

ActiveSupport::TimeZone.new('America/New_York').local_to_utc(t)

Cela dit de convertir cette heure locale (en utilisant le fuseau) en utc. Si vous avez Time.zone alors vous pouvez bien sûr

Time.zone.local_to_utc(t)

Cette méthode n'utilise pas le fuseau horaire associé à t - elle suppose qu'il s'agit du fuseau horaire local à partir duquel vous effectuez la conversion.

Un cas limite dont il faut se prémunir ici est celui des transitions DST : l'heure locale que vous spécifiez peut ne pas exister ou être ambiguë.

51voto

Ievgen Points 549

Je viens de rencontrer le même problème et voici ce que je vais faire :

t = t.asctime.in_time_zone("America/New_York")

Voici le documentation sur le temps de montée

24voto

Brian Points 722

Si vous utilisez Rails, voici une autre méthode qui s'inspire de la réponse d'Eric Walsh :

def set_in_timezone(time, zone)
  Time.use_zone(zone) { time.to_datetime.change(offset: Time.zone.now.strftime("%z")) }
end

7voto

j_mcnally Points 4023

Vous devez ajouter le décalage horaire à votre heure après l'avoir convertie.

La façon la plus simple de procéder est la suivante :

t = Foo.start_time.in_time_zone("America/New_York")
t -= t.utc_offset

Je ne vois pas très bien pourquoi vous voudriez faire cela, même s'il est probablement préférable de travailler avec les temps tels qu'ils sont construits. Je pense qu'il serait utile d'avoir quelques informations sur la raison pour laquelle vous avez besoin de décaler l'heure et les fuseaux horaires.

6voto

Peter Alfvin Points 14712

En fait, je pense que vous devez soustraire le décalage après l'avoir converti, comme dans :

1.9.3p194 :042 > utc_time = Time.now.utc
=> 2013-05-29 16:37:36 UTC
1.9.3p194 :043 > local_time = utc_time.in_time_zone('America/New_York')
 => Wed, 29 May 2013 12:37:36 EDT -04:00
1.9.3p194 :044 > desired_time = local_time-local_time.utc_offset
 => Wed, 29 May 2013 16:37:36 EDT -04:00

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X