strf rails month convert ruby-on-rails ruby string date

ruby-on-rails - rails - ruby time format



Cómo verificar si una cadena es una fecha válida (14)

Tengo una cadena: "31-02-2010" y quiero verificar si es o no una fecha válida. ¿Cuál es la mejor manera de hacerlo?

Necesito un método que devuelva verdadero si la cadena es una fecha válida y falso si no lo es.


Una solución más estricta

Es más fácil verificar la exactitud de una fecha si especifica el formato de fecha que espera. Sin embargo, incluso entonces, Ruby es un poco tolerante con mi caso de uso:

Date.parse("Tue, 2017-01-17", "%a, %Y-%m-%d") # works Date.parse("Wed, 2017-01-17", "%a, %Y-%m-%d") # works - !?

Claramente, al menos una de estas cadenas especifica el día de la semana equivocado, pero Ruby felizmente ignora eso.

Aquí hay un método que no; valida que date.strftime(format) convierta de nuevo a la misma cadena de entrada que analizó con Date.strptime según el format .

module StrictDateParsing # If given "Tue, 2017-01-17" and "%a, %Y-%m-%d", will return the parsed date. # If given "Wed, 2017-01-17" and "%a, %Y-%m-%d", will error because that''s not # a Wednesday. def self.parse(input_string, format) date = Date.strptime(input_string, format) confirmation = date.strftime(format) if confirmation == input_string date else fail InvalidDate.new( "''#{input_string}'' parsed as ''#{format}'' is inconsistent (eg, weekday doesn''t match date)" ) end end InvalidDate = Class.new(RuntimeError) end


Aquí hay un trazador de líneas simple:

DateTime.parse date rescue nil

Probablemente no recomendaría hacer exactamente esto en cada situación en la vida real, ya que obligaría a la persona que llama a verificar nulo, por ejemplo. particularmente al formatear. Si devuelve un error de fecha predeterminado, puede ser más amigable.


Date.parse no planteado excepción para este ejemplo:

Date.parse("12!12*2012") => Thu, 12 Apr 2018 Date.parse("12!12&2012") => Thu, 12 Apr 2018

Yo prefiero esta solución:

Date.parse("12!12*2012".gsub(/[^/d,/.,/-]/, '''')) => ArgumentError: invalid date Date.parse("12-12-2012".gsub(/[^/d,/.,/-]/, '''')) => Wed, 12 Dec 2012 Date.parse("12.12.2012".gsub(/[^/d,/.,/-]/, '''')) => Wed, 12 Dec 2012


Las fechas de análisis se pueden ejecutar en algunos programas, especialmente cuando están en formato MM / DD / AAAA o DD / MM / AAAA, como fechas cortas utilizadas en EE. UU. O Europa.

Date#parse intenta averiguar qué usar, pero hay muchos días en un mes a lo largo del año en que la ambigüedad entre los formatos puede causar problemas de análisis.

Recomiendo descubrir cuál es el LOCALE del usuario, luego, en base a eso, sabrá cómo analizar inteligentemente usando Date.strptime . La mejor forma de encontrar dónde se encuentra un usuario es preguntárselo durante el registro y luego proporcionar una configuración en sus preferencias para cambiarlo. Asumiendo que puede desenterrarlo mediante alguna heurística inteligente y no molestar al usuario por esa información, es propenso a fallar así que solo pregunte.

Esta es una prueba usando Date.parse . Estoy en los Estados Unidos:

>> Date.parse(''01/31/2001'') ArgumentError: invalid date >> Date.parse(''31/01/2001'') #=> #<Date: 2001-01-31 (4903881/2,0,2299161)>

El primero fue el formato correcto para los EE. UU .: mm / dd / aaaa, pero a Date no le gustó. El segundo era correcto para Europa, pero si sus clientes son predominantemente estadounidenses, obtendrá muchas fechas mal analizadas.

Ruby''s Date.strptime se usa como:

>> Date.strptime(''12/31/2001'', ''%m/%d/%Y'') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>


Método:

require ''date'' def is_date_valid?(d) Date.valid_date? *"#{Date.strptime(d,"%m/%d/%Y")}".split(''-'').map(&:to_i) rescue nil end

Uso:

config[:dates].split(",").all? { |x| is_date_valid?(x)}

Esto devuelve verdadero o falso si config [: fechas] = "12/10 / 2012,05 / 09/1520"


Me gustaría extender la clase de Date .

class Date def self.parsable?(string) begin parse(string) true rescue ArgumentError false end end end

ejemplo

Date.parsable?("10-10-2010") # => true Date.parse("10-10-2010") # => Sun, 10 Oct 2010 Date.parsable?("1") # => false Date.parse("1") # ArgumentError: invalid date from (pry):106:in `parse''


Otra forma de validar la fecha:

date_hash = Date._parse(date.to_s) Date.valid_date?(date_hash[:year].to_i, date_hash[:mon].to_i, date_hash[:mday].to_i)


Prueba regex para todas las fechas:

/(/d{1,2}[-//]/d{1,2}[-//]/d{4})|(/d{4}[-//]/d{1,2}[-//]/d{1,2})/.match("31-02-2010")

Solo para su formato con ceros a la izquierda, año último y guiones:

/(/d{2}-/d{2}-/d{4})/.match("31-02-2010")

[- /] significa - o /, la barra diagonal debe ser escapada. Puedes probar esto en http://gskinner.com/RegExr/

agregue las siguientes líneas, se resaltarán todas si usa la primera expresión regular, sin la primera y última / (son para usar en el código Ruby).

2004-02-01 2004/02/01 01-02-2004 1-2-2004 2004-2-1


Publicar esto porque podría ser útil para alguien más tarde. No tengo idea si esta es una "buena" manera de hacerlo o no, pero funciona para mí y es extensible.

class String def is_date? temp = self.gsub(/[-.//]/, '''') [''%m%d%Y'',''%m%d%y'',''%M%D%Y'',''%M%D%y''].each do |f| begin return true if Date.strptime(temp, f) rescue #do nothing end end return false end end

Este add-on para la clase String te permite especificar tu lista de delimitadores en la línea 4 y luego tu lista de formatos válidos en la línea 5. No es ciencia ficción, pero hace que sea muy fácil de extender y te permite simplemente verificar una cadena como esta:

"test".is_date? "10-12-2010".is_date? params[:some_field].is_date? etc.


Puede intentar lo siguiente, que es la manera más simple:

"31-02-2010".try(:to_date)

Pero debes manejar la excepción.


Date.valid_date? *date_string.split(''-'').reverse.map(&:to_i)


d, m, y = date_string.split ''-'' Date.valid_date? y.to_i, m.to_i, d.to_i


require ''date'' #new_date and old_date should be String # Note we need a () def time_between(new_date, old_date) new_date = (Date.parse new_date rescue nil) old_date = (Date.parse old_date rescue nil) return nil if new_date.nil? || old_date.nil? (new_date - old_date).to_i end puts time_between(1,2).nil? #=> true puts time_between(Time.now.to_s,Time.now.to_s).nil? #=> false


require ''date'' begin Date.parse("31-02-2010") rescue ArgumentError # handle invalid date end