Cómo comprobar si una cadena es una fecha válida
Tengo una cadena: "31-02-2010"
y quiero comprobar si es o no una fecha válida.
¿Cuál es la mejor manera de hacerlo?
Necesito un método que devuelva true si la cadena es una fecha válida y false si no lo es.
14 answers
require 'date'
begin
Date.parse("31-02-2010")
rescue ArgumentError
# handle invalid date
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-05 16:19:55
d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-06 23:01:12
Aquí hay un simple trazador de líneas:
DateTime.parse date rescue nil
Probablemente no recomendaría hacer exactamente esto en todas las situaciones de la vida real, ya que obliga a la persona que llama a comprobar si no hay nada, por ejemplo. particularmente al formatear. Si devuelve una fecha|error predeterminado puede ser más amigable.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-10 21:20:28
Las fechas de análisis pueden encontrarse en algunos gotcha, especialmente cuando están en un formato MM/DD/AAAA o DD/MM/AAAA, como las fechas cortas utilizadas en Estados Unidos o Europa.
Date#parse
intenta averiguar cuál usar, pero hay muchos días en un mes a lo largo del año cuando la ambigüedad entre los formatos puede causar problemas de análisis.
Yo recomendaría averiguar cuál es la configuración regional del usuario, entonces, basado en eso, usted sabrá cómo analizar inteligentemente usando Date.strptime
. La mejor manera de encontrar donde un el usuario se encuentra es preguntarles durante el registro, y luego proporcionar una configuración en sus preferencias para cambiarla. Suponiendo que puede desenterrarlo por alguna heurística inteligente y no molestar al usuario por esa información, es propenso al fracaso, 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 Date no le gustó. El segundo fue correcto para Europa, pero si sus clientes son predominantemente estadounidenses, obtendrá un muchas fechas mal analizadas.
Ruby Date.strptime
se usa como:
>> Date.strptime('12/31/2001', '%m/%d/%Y') #=> #<Date: 2001-12-31 (4904549/2,0,2299161)>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-18 23:10:36
Date.valid_date? *date_string.split('-').reverse.map(&:to_i)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-24 17:20:59
Me gustaría extender la clase 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'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-16 10:16:58
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-19 09:57:42
Publicando esto porque podría ser útil para alguien más tarde. No hay idea de 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 complemento para la clase String le permite especificar su lista de delimitadores en la línea 4 y luego su lista de formatos válidos en la línea 5. No es ciencia de cohetes, pero hace que sea muy fácil de extender y le permite simplemente comprobar una cadena como esta:
"test".is_date?
"10-12-2010".is_date?
params[:some_field].is_date?
etc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 21:12:54
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 iniciales, el último año y guiones:
/(\d{2}-\d{2}-\d{4})/.match("31-02-2010")
El [ - / ] significa o bien - o /, la barra diagonal debe ser escapada. Puedes probar esto en http://gskinner.com/RegExr /
Agregue las siguientes líneas, todas se resaltarán si usa la primera expresión regular, sin el primero y el último / (son para usar en código ruby).
2004-02-01
2004/02/01
01-02-2004
1-2-2004
2004-2-1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-18 14:00:29
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 demasiado tolerante para 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 incorrecto, pero Ruby felizmente ignora eso.
Aquí hay un método que no lo hace; valida que date.strftime(format)
convierte de nuevo a la misma cadena de entrada con la que analizóDate.strptime
según 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-17 17:06:04
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-18 08:43:16
Puedes probar lo siguiente, que es de la manera más sencilla:
"31-02-2010".try(:to_date)
Pero necesita manejar la excepción.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-19 18:47:55
Fecha.analizar excepción no planteada para estos ejemplos:
Date.parse("12!12*2012")
=> Thu, 12 Apr 2018
Date.parse("12!12&2012")
=> Thu, 12 Apr 2018
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-10 13:19:18
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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-28 20:52:28