Domanda

Ho una domanda basata su tempo di rotaie che ha un comportamento sensibile fuso orario strano, anche se per quanto ne so che sto utilizzando UTC. In poche parole, queste query danno risposte diverse:

>> Model.find(:all,:conditions=>['created_at<=?',(Time.now-1.hours).gmtime]).length
=> 279
>> Model.find(:all,:conditions=>['created_at<=?',(Time.now-1.hours)]).length
=> 280

Se il DB fa effettivamente contenere un modello creato nelle ultime ore, e il numero totale di modelli è 280. Quindi, solo la prima interrogazione è corretta.

Tuttavia, in environment.rb ho:

config.time_zone = 'UTC'

Il fuso orario del sistema (come riportato da 'data') è BST (che è GMT + 1) - in modo in qualche modo questo finisce sempre trattati come UTC e le query di rottura.

Questo è mi ha causato problemi di ogni genere, come ho bisogno di parametrizzare la query passando in tempi diversi a un'azione (che vengono poi convertiti utilizzando Time.parse ()), e anche se mando in tempi UTC, questo 'off di un'ora' problema DST ritaglia un sacco. Anche usando '.gmtime ()' non sembra sempre di risolvere il problema.

Ovviamente la differenza è causata in qualche modo da una conversione implicita da qualche parte con conseguente BST essere erroneamente trattati come UTC, ma perché? Non fa rotaie memorizzare i timestamp in UTC? Non è la classe fuso orario Tempo a conoscenza? Sto usando Rails 2.2.2

Allora, cosa sta succedendo qui - e qual è il modo sicuro per programmare intorno ad esso?

modifica, alcune informazioni aggiuntive per mostrare ciò che la DB e la classe Tempo stanno facendo:

>> Model.find(:last).created_at
=> Tue, 11 Aug 2009 20:31:07 UTC +00:00
>> Time.now
=> Tue Aug 11 22:00:18 +0100 2009
>> Time.now.gmtime
=> Tue Aug 11 21:00:22 UTC 2009
È stato utile?

Soluzione

La classe Time non è direttamente a conoscenza del tuo fuso orario configurato. Rails 2.1 ha aggiunto un po 'di supporto del fuso orario, ma Time sarà ancora agire il fuso orario locale. Questo è il motivo per cui Time.now restituisce un tempo BST.

Quello che probabilmente si desidera è quello di interagire con Time.zone. È possibile chiamare metodi su questo come si farebbe con la classe Tempo sé, ma tornerà nel fuso orario specificato.

Time.zone.now # => Tue, 11 Aug 2009 21:31:45 UTC +00:00
Time.zone.parse("2:30 PM Aug 23, 2009") # => Sun, 23 Aug 2009 14:30:00 UTC +00:00

Un'altra cosa che dovete stare attenti con è se mai fare query sul database in cui si confrontano i tempi, ma assicurarsi di utilizzare il tempo UTC (anche se si ha un fuso orario diverso specificato), in quanto Rails memorizza sempre UTC in il database.

Item.all(:conditions => ["published_at <= ?", Time.now.utc])

Inoltre, invece di fare Time.now-1.hour 1.hour.ago. E 'più facile da leggere e Rails utilizzeranno automaticamente il fuso orario configurato.

Altri suggerimenti

Il fuso orario è necessario impostare è nel Regno Unito, questo si occuperà automaticamente BST

Time.zone = 'UK'
Time.zone.now
 => Sun, 17 Oct 2010 02:09:54 BST +01:00
start_date_format = DateTime.strptime(@start_date, date_format)
start_date_format_with_hour = 
DateTime.strptime((start_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format)

end_date_format = DateTime.strptime(@end_date, date_format)
end_date_format_with_hour = DateTime.strptime((end_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format)

@filters_date = "invoices.created_at >= ? AND invoices.created_at < ?", start_date_format_with_hour, end_date_format_with_hour
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top