2012-03-15 14 views
13

Si paso una columna String en Datetime al crear un nuevo objeto de RA, se analiza de forma automática:ActiveRecord cadena de análisis a fecha y hora?

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> 

¿Cómo Rails, o ActiveRecord, hacer esta magia? ¿Qué método usa?

Respuesta

17

Rails agrega un método to_date al String. Su fuente es simple:

# 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 es nativa a Ruby (el mismo método es llamado por Date.parse) y es where the real work is done.

Primero utiliza una expresión regular para eliminar símbolos extraños de la cadena, luego la pasa a otros métodos como _parse_eu, _parse_iso, _parse_dot y así sucesivamente. Cada uno de estos usa sus propias expresiones regulares y otros métodos para ver si se trata de una fecha que comprende y extraer la información significativa de la misma. Una vez que uno de ellos "funciona" (es decir, devuelve verdadero), el resto se omite. Finalmente, de vuelta en _parse, la información extraída se usa para construir una fecha y hora, haciendo un poco más de trabajo para averiguar cosas como verificar el día de la semana y si un valor de año de "12" debe significar 1912 o 2012.

Los documentos llaman a esto un método heurístico, lo que podría interpretarse como que arroja un montón de posibilidades en la pared para ver qué se adhiere. Está bastante mal documentado pero funciona notablemente bien.

1

Probablemente desee utilizar Date.strptime(str).

+1

'strptime' tiene que conocer el formato de fecha de otro modo sería utilizar su formato predeterminado. Pero AR puede analizar mágicamente fechas en varios formatos. –

+0

Asegúrese de estar probando todos los formatos de fecha que un usuario podría presentar. No son siempre deterministas. – aceofspades

2

También hay to_datetime si necesita tiempo.

0

como otros comentarios y la documentación sugiere, String#to_datetime "Convierte una cadena en un valor 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 
Cuestiones relacionadas