2012-03-15 13 views
13

Se mi passa una colonna String in Datetime durante la creazione di nuovo oggetto AR, sarà analizzare automaticamente:ActiveRecord analizza la stringa in data/ora?

1.9.2p290 :011 > Movie.new(:release_date=>"21-Nov-1990") 
=> #<Movie id: nil, release_date: "1990-11-21 00:00:00", created_at: nil, updated_at: nil> 

Come si fa Rails, o ActiveRecord, fare questa magia? Quale metodo usa?

risposta

17

Rails aggiunge un metodo to_date a String. La sua fonte è semplice:

# File activesupport/lib/active_support/core_ext/string/conversions.rb, line 42 
def to_date 
    return nil if self.blank? 
    ::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday)) 
end 

Date._parse è nativo a Ruby (lo stesso metodo viene chiamato da Date.parse) ed è where the real work is done.

Prima utilizza un'espressione regolare per rimuovere simboli estranei dalla stringa, quindi passa ad altri metodi come _parse_eu, _parse_iso, _parse_dot e così via. Ognuno di questi utilizza le proprie espressioni regolari e altri metodi per vedere se è una data che capisce ed estrarre le informazioni significative da esso. Una volta che uno di essi "funziona" (cioè restituisce true), il resto viene saltato. Infine, tornando in _parse, le informazioni estratte vengono utilizzate per creare una data e un'ora, facendo un po 'più di lavoro per capire cose come controllare il giorno della settimana e se un valore di anno "12" dovrebbe significare 1912 o 2012.

I documenti lo chiamano un metodo euristico, che potrebbe essere interpretato come un modo per gettare un sacco di possibilità sul muro per vedere cosa si attacca. È piuttosto mal documentato, ma funziona molto bene.

1

Probabilmente si desidera utilizzare Date.strptime(str).

+1

'strptime' deve conoscere il formato della data, altrimenti avrebbe usato il suo formato di default. Ma AR può analizzare magicamente le date in diversi formati. –

+0

Assicurati di testare tutti i formati di data che un utente potrebbe presentare. Non sono sempre deterministici. – aceofspades

2

C'è anche to_datetime se avete bisogno del tempo.

0

Come altri commenti e la documentazione suggerisce, String#to_datetime "Converte una stringa in un valore DateTime.":

"1-1-2012".to_datetime   # => Sun, 01 Jan 2012 00:00:00 +0000 
"01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000 
"2012-12-13 12:50".to_datetime # => Thu, 13 Dec 2012 12:50:00 +0000 
"12/13/2012".to_datetime   # => ArgumentError: invalid date 
Problemi correlati