Tengo una cadena: "31-02-2010"
y quiero comprobar si es una fecha válida o no. ¿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.
Tengo una cadena: "31-02-2010"
y quiero comprobar si es una fecha válida o no. ¿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.
Respuestas:
require 'date'
begin
Date.parse("31-02-2010")
rescue ArgumentError
# handle invalid date
end
Aquí hay un trazador de líneas simple:
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 verificar nulo, por ejemplo. particularmente al formatear. Si devuelve una fecha predeterminada | error, puede ser más amigable.
Date.strptime(date, '%d/%m/%Y') rescue nil
rescue
desaconseja el uso de inline .
d, m, y = date_string.split '-'
Date.valid_date? y.to_i, m.to_i, d.to_i
is_valid?
? Probé 1.8, 2.0 y 2.1. Ninguno de ellos parece tener ese. Sin valid_date?
embargo, todos parecen haberlo hecho .
Las fechas de análisis pueden encontrarse con algunos errores, especialmente cuando están en formato MM / DD / YYYY o DD / MM / YYYY, como las fechas cortas utilizadas en EE. UU. O Europa.
Date#parse
intenta averiguar cuál usar, pero hay muchos días en un mes durante todo el año en los que la ambigüedad entre los formatos puede causar problemas de análisis.
Recomendaría averiguar cuál es el LOCAL del usuario, luego, basado en eso, sabrá cómo analizar inteligentemente usando Date.strptime
. La mejor manera de saber dónde se encuentra un usuario es preguntarle durante el registro y luego proporcionar una configuración en sus preferencias para cambiarla. Suponiendo que pueda desenterrarlo mediante alguna heurística inteligente y no molestar al usuario por esa información, es propenso a fallar, así que pregunte.
Esta es una prueba con 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ó. La segunda era correcta para Europa, pero si sus clientes residen predominantemente en EE. UU., Obtendrá 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)>
01/01/2014
, ¿cuál es el mes y cuál es el día? En los Estados Unidos el mes sería el primero, el resto del mundo sería el segundo.
Date.valid_date? *date_string.split('-').reverse.map(&:to_i)
require "date"
primero o obtendrá un "método indefinido".
Date.valid_date? *Array.new(3).zip(date_string.split('-')).transpose.last.reverse.map(&:to_i)
Me gustaría extender la Date
clase.
class Date
def self.parsable?(string)
begin
parse(string)
true
rescue ArgumentError
false
end
end
end
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)
Pruebe las expresiones regulares 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, último año y guiones:
/(\d{2}-\d{2}-\d{4})/.match("31-02-2010")
el [- /] significa - o /, la barra inclinada debe escaparse. Puede probar esto en http://gskinner.com/RegExr/
agregue las siguientes líneas, todas se resaltarán si usa la primera expresión regular, sin la primera y la última / (son para usar en código ruby).
2004-02-01
2004/02/01
01-02-2004
1-2-2004
2004-2-1
32-13-2010
cuál es incorrecta.
'00/00/0000'
y '99-99/9999'
son posibles candidatos.
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 lo ignora.
Aquí hay un método que no lo hace; valida que date.strftime(format)
vuelve a convertir a la misma cadena de entrada con la que analizó de Date.strptime
acuerdo con 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
Date.today().iso8601
); %m
se rellena con ceros. Si desea algo diferente, consulte ruby-doc.org/stdlib-2.4.0/libdoc/date/rdoc/…
Publicar esto porque podría ser útil para alguien más adelante. No tengo idea de si esta es una "buena" forma de hacerlo o no, pero funciona para mí y es ampliable.
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 espacial, pero hace que sea realmente fácil de extender y le permite simplemente verificar una cadena como esta:
"test".is_date?
"10-12-2010".is_date?
params[:some_field].is_date?
etc.
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
Puede probar lo siguiente, que es la forma más sencilla:
"31-02-2010".try(:to_date)
Pero debes manejar la excepción.
Date.parse no generó una excepción 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
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] = "10/12 / 2012,05 / 09/1520"