webentwicklung-frage-antwort-db.com.de

Wie ändere ich den Zonenversatz für eine bestimmte Zeit in Ruby on Rails?

Ich habe eine Variable foo, die eine Zeit enthält, sagen wir heute um 16 Uhr, aber der Zonenversatz ist falsch, d. H. Sie befindet sich in der falschen Zeitzone. Wie ändere ich die Zeitzone?

Wenn ich es drucke, bekomme ich

Fri Jun 26 07:00:00 UTC 2009

Es gibt also keinen Versatz, und ich möchte den Versatz auf -4 oder Eastern Standard Time setzen.

Ich würde erwarten, in der Lage zu sein, nur den Offset als eine Eigenschaft des Time-Objekts festzulegen, aber das scheint nicht verfügbar zu sein?

24
Janak

Ich verwende Rails 2.0, bevor der Code hinzugefügt wird, mit dem die weppos-Lösung funktioniert. Hier ist was ich getan habe

# Silly hack, because sometimes the input_date is in the wrong timezone
temp = input_date.to_time.to_a
temp[8] = true
temp[9] = "Eastern Daylight Time"
input_date = Time.local(*temp)

Ich zerlege die Zeit in ein Array mit 10 Elementen, ändere die Zeitzone und wandle das Array dann wieder in eine Zeit um.

2
Janak

Sie sagen nicht explizit, wie Sie die tatsächliche Variable erhalten, aber da Sie die Zeitklasse erwähnen, gehe ich davon aus, dass Sie die Zeit dafür haben, und ich werde in meiner Antwort darauf verweisen

Die Zeitzone ist tatsächlich Teil der Zeitklasse (in Ihrem Fall wird die Zeitzone als UTC angezeigt). Time.now gibt den Offset von UTC als Teil der Time.now-Antwort zurück.

>> local = Time.now
=> 2012-08-13 08:36:50 +0000
>> local.hour
=> 8
>> local.min
=> 36
>> 


... in diesem Fall bin ich zufällig in der gleichen Zeitzone wie GMT

Zwischen Zeitzonen konvertieren

Die einfachste Möglichkeit, die ich gefunden habe, besteht darin, den Versatz im Format "+/- HH: MM" in die Methode "getlocal" zu ändern. Nehmen wir an, ich möchte zwischen der Zeit in Dublin und der Zeit in New York konvertieren

?> dublin = Time.now
=> 2012-08-13 08:36:50 +0000
>> new_york = dublin + Time.zone_offset('EST')
=> 2012-08-13 08:36:50 +0000
>> dublin.hour
=> 8
>> new_york.hour
=> 3

Angenommen, "EST" ist der Name der Zeitzone für New York, wie Dan manchmal betont, dass "EDT" die richtige TZ ist.

17
Chris McCauley

Wenn gegeben:

2011-10-25 07:21:35 -700

sie wollen:

2011-10-25 07:21:35 UTC

dann mach:

Time.parse(Time.now.strftime('%Y-%m-%d %H:%M:%S UTC')).to_s
15
99miles

Dies nutzt die Tatsache aus, dass Time#asctime die Zone nicht enthält.

Angesichts einer Zeit:

>> time = Time.now
=> 2013-03-13 13:01:48 -0500

Erzwinge es in eine andere Zone (dies gibt einen ActiveSupport::TimeWithZone zurück):

>> ActiveSupport::TimeZone['US/Pacific'].parse(time.asctime)
=> Wed, 13 Mar 2013 13:01:48 PDT -07:00

Beachten Sie, dass die ursprüngliche Zone vollständig ignoriert wird. Wenn ich die ursprüngliche Zeit in utc konvertiere, sieht das Ergebnis anders aus:

>> ActiveSupport::TimeZone['US/Pacific'].parse(time.getutc.asctime)
=> Wed, 13 Mar 2013 18:01:48 PDT -07:00

Sie können to_time oder to_datetime für das Ergebnis verwenden, um eine entsprechende Time oder DateTime zu erhalten.

Diese Frage verwendet einen interessanten Ansatz mit DateTime#change, um den tz-Offset festzulegen. (Denken Sie daran, dass es mit ActiveSupport einfach ist, zwischen Time und DateTime zu konvertieren.) Der Nachteil ist, dass keine DST-Erkennung vorhanden ist. Sie müssen dies manuell mit dem current_period von TZInfo tun.

14
Kelvin

...

>> Time.at(Time.now.utc + Time.zone_offset('PST'))
=> Mon Jun 07 22:46:22 UTC 2010
>> Time.at(Time.now.utc + Time.zone_offset('PDT'))
=> Mon Jun 07 23:46:26 UTC 2010
>> Time.at(Time.now.utc + Time.zone_offset('CST'))
=> Tue Jun 08 00:46:32 UTC 2010

Ein Hinweis: Stellen Sie sicher, dass das aktuelle Zeitobjekt zuerst auf UTC-Zeit eingestellt ist. Andernfalls versucht Ruby, das Zeitobjekt in Ihre lokale Zeitzone zu konvertieren und löst so die Berechnung aus. In diesem Fall können Sie die angepasste Zeit immer durch Anwenden von ".utc" am Ende der obigen Anweisungen ermitteln.

11
ALW

Für diejenigen, die (wie ich) auf der Suche nach einer Nicht-Rails-Lösung darauf gestoßen sind, hat TZInfo diese für mich gelöst ...

require 'tzinfo'
def adjust_time time, time_zone="America/Los_Angeles"
    return TZInfo::Timezone.get(time_zone).utc_to_local(time.utc)
end

puts adjust_time(Time.now) 
#=> PST or PDT
puts adjust_time(Time.now, "America/New_York")
#=> EST or EDT

Dies behandelt auch die Sommerzeit, was ich brauchte, was oben nicht behandelt wurde.

Siehe: http://tzinfo.rubyforge.org/

10
jmervine

suchen Sie in Ihrer environment.rb nach der folgenden Zeile.

# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names.
config.time_zone = 'UTC'

Beachten Sie, dass ActiveRecord und Rails die Uhrzeit intern immer als UTC behandeln.

5
Simone Carletti

Hier ist, was für mich gearbeitet hat ...

def convert_zones(to_zone)
   to_zone_time = to_zone.localtime
end


# have your time set as time

time = convert_zones(time)
time.strftime("%b #{day}, %Y (%a) #{hour}:%M %p %Z")
1
Kris

Dies ist, was ich getan habe, da ich keine Rails verwende und keine Nicht-Core-Edelsteine ​​verwenden möchte.

t = Time.now # my local time - which is GMT
zone_offset = 3600 # offset for CET - which is my target time zone
zone_offset += 3600 if t.dst? # an extra hour offset in summer
time_cet = Time.mktime(t.sec, t.min, t.hour, t.mday, t.mon, t.year, nil, nil, t.dst?, zone_offset)
0
Chris Kimpton

Es ist wahrscheinlich eine gute Idee, die Zeit als UTC zu speichern und sie dann in einer bestimmten Zeitzone anzuzeigen, wenn sie angezeigt wird. Hier ist eine einfache Möglichkeit, dies zu tun (funktioniert in Rails 4, bei früheren Versionen unsicher).

t = Time.now.utc

=> 2016-04-19 20:18:33 UTC

t.in_time_zone("EST")

=> Tue, 19 Apr 2016 15:18:33 EST -05:00

Wenn Sie es jedoch wirklich in einer bestimmten Zeitzone speichern möchten, können Sie das ursprüngliche Time-Objekt einfach auf sich selbst setzen.

t = t.in_time_zone("EST")
0
ryan0

Beim Parsen einer Zeit

Es würde mich interessieren, wie Sie die Variable foo einstellen.

Wenn Sie eine Zeitzeichenfolge ohne Zeitzone analysieren (was ich während eines Datenimports getan habe), können Sie String#in_time_zone verwenden, um die Zeitzone während des Analysierens zu erzwingen:

"Fri Jun 26 2019 07:00:00".in_time_zone( "Eastern Time (US & Canada)" ) 
# => Wed, 26 Jun 2019 07:00:00 EDT -04:00

Funktioniert wie ein Zauber und ist super sauber.

0
Joshua Pinter

Option 1

Verwende date_time_attribute gem :

my_date_time = DateTimeAttribute::Container.new(Time.zone.now)
my_date_time.date_time           # => 2001-02-03 22:00:00 KRAT +0700
my_date_time.time_zone = 'Moscow'
my_date_time.date_time           # => 2001-02-03 22:00:00 MSK +0400

Option 2

Wenn time als Attribut verwendet wird, können Sie dasselbe date_time_attribute gem verwenden:

class Task
  include DateTimeAttribute
  date_time_attribute :due_at
end

task = Task.new
task.due_at_time_zone = 'Moscow'
task.due_at                      # => Mon, 03 Feb 2013 22:00:00 MSK +04:00
task.due_at_time_zone = 'London'
task.due_at                      # => Mon, 03 Feb 2013 22:00:00 GMT +00:00
0
Sergei Zinin