2011-10-26 32 views
17

ho una stringa che ho interpretare da DateTime.strptime. Il fuso orario della data data la stringa è CET ma di Ruby crea un oggetto UTC DateTime che ovviamente ha un offset di 2 ore.strptime con fuso orario

Attualmente sto lavorando al problema con DateTime.strptime().change(:offset => "+0020") ma sono abbastanza sicuro che questo non è il modo in cui è pensato per funzionare.

Qualcuno può illuminarmi sul modo corretto di fare questo?

+0

se si è in un paese con fuso orario CEST/CET, un offset fisso non funzionerà. Interessato anche a questo, non vedo come effettuare l'analisi strptime per il fuso orario corrente (ma non il valore adesso, quello giusto a seconda della stringa analizzata). – tokland

risposta

-1

non posso eliminare una risposta accettata

Come @LeeJarvis rilevare nella sezione commenti qui sotto, Chronic.parse non accetta un'opzione :time_class. Quindi questa risposta è bacato e mentre sembra che funziona, non è così (a meno che non permette il passaggio cronica un'opzione :time_class presto.)


La gemma cronica è davvero potente.

lo uso così:

Chronic.parse("next 5:00 pm", 
:time_class => ActiveSupport::TimeZone.new(User.first.time_zone)).utc 

Nel mio esempio di cui sopra, User.first.time_zone è "Pacifico (USA & Canada)".

cronica supporta molti formati in modo da controllare fuori a https://github.com/mojombo/chronic

Assicurati di passare l'opzione :time_class e di convertire in UTC (nella documentazione, set croniche :time_class prima di chiamare parse. Evito questo approccio perché esso potrebbe causare altre parti in tutta l'applicazione non al lavoro)

documentazione del fuso orario è a http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html

+0

Questa risposta non è corretta. 'parse()' non accetta un'opzione 'time_class'. È impostato direttamente sulla classe 'Chronic'. Questo alla fine cambierà nelle versioni future di Chronic, anche se –

+0

My bad ... rimuoverò fino a quando questa opzione non sarà disponibile =) – Abdo

+0

Erm ... Non riesco a cancellare una risposta accettata. Commenterò sopra. – Abdo

9

lo uso come segue:

ruby-1.9.2-head :001 > require 'date' 
=> true 
ruby-1.9.2-head :002 > fmt = "%m-%d-%Y %H:%M:%S %Z" 
=> "%m-%d-%Y %H:%M:%S %Z" 
ruby-1.9.2-head :003 > DateTime.strptime "10-26-2011 10:16:29 CET", fmt 
=> #<DateTime: 2011-10-26T10:16:29+01:00 (212186380589/86400,1/24,2299161)> 
ruby-1.9.2-head :004 > DateTime.strptime "10-26-2011 10:16:29 UTC", fmt 
=> #<DateTime: 2011-10-26T10:16:29+00:00 (212186384189/86400,0/1,2299161)> 
ruby-1.9.2-head :005 > DateTime.strptime "10-26-2011 10:16:29 PST", fmt 
=> #<DateTime: 2011-10-26T10:16:29-08:00 (212186412989/86400,-1/3,2299161)> 

E 'quello che vuoi dire?

+2

Non ho una stringa che determini il fuso orario nella mia stringa analizzata. il 10-26-2011 10:16:29 invece di "10-26-2011 10:16:29 CET" – Nicolas

+0

Hai risolto il mio problema, posso solo "" 09-19-2012 11:08:44 "+" CST "'. Penso che la tua sia la risposta corretta. – mwoods79

+0

E quando entri nell'ora legale? Non dovrebbe questo + "CST" essere più informato? Come da commento sopra, sarebbe bello se potessimo scegliere quello basato sul tempo che è appena stato formattato ... sto imparando a odiare i fusi orari. –

0

è possibile convertire la data di fuso orario con to_time_in_current_zone. Per esempio:

Date.strptime('04/07/1988', '%m/%d/%Y').to_time_in_current_zone 
+3

http://apidock.com/rails/Date/to_time_in_current_zone il metodo è ammortizzato scusa :( – Brandt

1

ero "strptiming" questa stringa:

19/05/2014 8:13:26 a.m. 

Un timestamp locale, che è nel mio caso è Auckland NZ senza un timbro fuso orario nella stringa come si può vedere.

Come meglio posso dire Time.strptime utilizza il fuso orario del server come base.

Nella mia situazione, e la buona prassi generale, i miei server gestiscono nel fuso orario UTC così ogni parse della stringa ha finito per creare un oggetto di tempo, il tempo di 0000 (UTC):

2014-05-19 08:13:26 +0000 

Poi la conversione a dato:

Mon, 19 May 2014 20:13:26 NZST +12:00 

che come si può vedere è di 12 ore (compensato l'UTC) entro e non oltre il tempo effettivo che volevo.

Ho provato a utilizzare il trucco +' Auckland', '...%Z' come sopra senza alcuna modifica. Ho quindi utilizzato il trucco + '+1200', '...%Z' come sopra, che ha funzionato correttamente.

Tuttavia ero preoccupato per l'ora legale, quindi l'analisi sarebbe da un'ora, quindi questo è quello che ho Finshed con:

Time.strptime(call_data[:datetime].gsub(/\./, "").gsub(/am/, "AM").gsub(/pm/, "PM") + (Time.zone.now.time_zone.utc_offset/3600).to_s.ljust(4,'0').rjust(6,' +'), '%d/%m/%Y %I:%M:%S %p %Z').in_time_zone(Time.zone) 

Risultato:

Mon, 19 May 2014 08:13:26 NZST +12:00 

Non è particolarmente elegante ma funziona.

0

Mi sono battuto su questo stesso problema cercando di analizzare una stringa di data da un modulo e salvarlo indipendentemente dal tempo del server. Il processo che ho seguito è come tale. Assicuro che i fusi orari RoR e Ruby sono impostati su UTC. Rende più facile se il server è in orario UTC pure.

sto Memorizzazione gli utenti versione locale con l'ActiveSupport: formato di fuso orario come US/Eastern ho una funzione di interpretare la data, che può rappresentare una stringa di data che non contiene nativamente un fuso orario o di compensato

# date_str looks something like this `12/31/2014 6:22 PM` 
# tz is a string containing an ActiveSupport::TimeZone name like `US/Eastern` 
def interpret_date(date_str, tz) 
    Time.use_zone tz do 
    parsed_dt = DateTime.strptime(date_str, '%m/%d/%Y %H:%M %p') 
    offset = parsed_dt.in_time_zone(tz).utc_offset 
    parsed_dt.advance(seconds: -(offset)).in_time_zone(tz) 
    end 
end 

Questo ovviamente non sembra una soluzione perfetta ma funziona. I passi per assicurare il fuso orario corretto sono:

  1. analizzare la stringa data in base al nostro format
  2. Estrarre l'offset in base al tempo in quel fuso orario UTC corrente (quello che dobbiamo fare questo se la data si è il parsing sembra essere in dst mentre l'ora locale non è dst per l'ora orientale questo assicurerà che il dst è locale all'ora analizzata)
  3. Converti l'ora nella locale di destinazione e concedi il tempo di spostarti con l'offset corretto aggiunto
1

Almeno a s di Rails 4.2 (forse in precedenza, non hanno testato) fino a quando si usa al posto del Time#strptimeDateTime.strptime, il fuso orario corrente viene applicata automaticamente:

> DateTime.strptime('12/28/2016 5:00 PM', '%m/%d/%Y %H:%M %p') 
=> Wed, 28 Dec 2016 17:00:00 +0000 

> Time.strptime('12/28/2016 5:00 PM', '%m/%d/%Y %H:%M %p') 
=> 2016-12-28 17:00:00 -0800 
3

Questo funziona in Rails 5:

Time.zone.strptime("2017-05-20 18:20:10", "%Y-%m-%d %H:%M:%S") 

Restituisce l'ora nel fuso orario specificato.