如何检查日期是否有效 (Ruby on Rails)

How to check if date is valid (Ruby on Rails)

提问人:Shruikan 提问时间:4/29/2022 最后编辑:Shruikan 更新时间:4/30/2022 访问量:421

问:

我有这个before_save功能:

def set_birth_date
    return unless pesel_changed?

    day = pesel[4..5]
    case pesel[2..3].to_i
    when 0..19
      month = pesel[2..3]
      year = pesel[0..1].prepend('19')
    when 20..39
      month = (pesel[2..3].to_i - 20).to_s
      year = pesel[0..1].prepend('20')
    when 40..59
      month = (pesel[2..3].to_i - 40).to_s
      year = pesel[0..1].prepend('21')
    when 60..79
      month = (pesel[2..3].to_i - 60).to_s
      year = pesel[0..1].prepend('22')
    end
      birth_date = Time.strptime("#{day}/#{month}/#{year}", '%d/%m/%Y')
    if birth_date.valid?
      self.birth_date = birth_date
    else
      errors.add(:pesel, I18n.t('activerecord.errors.models.profile.attributes.pesel.invalid'))
    end
  end

(小解释:如果条件尚未包含在函数中,则最后。我想做的就是保存birth_date如果有效,但如果它无效,我想添加错误。但有时它会给我这样的错误:

`strptime': invalid date or strptime format - `12/14/2022' `%d/%m/%Y' (ArgumentError)

如何检查Time.strptime(“#{day}/#{month}/#{year}”, '%d/%m/%Y') 是否有效?“有效?”和“valid_date?”不起作用。 几个月来,我可以做这样的事情

if month / 12 > 0
  <Handling error>
else
  <update>
end

但是几天来......这并不容易。有什么想法吗?

编辑: Pesel 是一个字符串。此函数从 pesel 编号中提取出生日期。Pesel 号码是 11 位数字,例如:

50112014574
50 - year of birth
11 - month of birth
20 - day of birth
14574 - Control number
Those "magic numbers' defines which year someone was born
If someone was born in 19XX, then month number is 1-12.
If someone was born in 20XX, then month number is 21-32 (month number + 20. Example pesel number: '50312014574', which means this person was born 20th November 2050
If someone was born 21XX, then month number is 41-52 (month nubmer + 40) Example pesel number: '50512014574', which means this person was born 20th November 2150 etc.

我正在处理现有数据库,我不能只验证 pesel 编号

Ruby-on-Rails 红宝石 日期 错误处理

评论

0赞 spickermann 4/29/2022
输入格式是什么?这种方法实际上有什么作用?所有这些神奇的数字意味着什么?pesel
0赞 kouroubel 4/29/2022
为什么日期无效?我会从那里开始......
0赞 Shruikan 4/29/2022
@spickermann 问题已编辑。更多解释在底部。
0赞 Shruikan 4/29/2022
@kouroubel 因为某些用户可能输入了一个随机的 pesel 编号,这可能会导致类似 56/18/<year 的日期>
0赞 kouroubel 4/29/2022
如何通过对用户输入进行一些验证来防止他们输入他们想要的任何数字?

答:

0赞 kouroubel 4/30/2022 #1

获得年份和月份后,您可能需要检查日期是否大于

n_days =  Time.days_in_month(month, year) 

评论

0赞 Shruikan 4/30/2022
这可能有效,但我必须在 if 中创建一个 if。第一个 if 用于检查月份是否存在,第二个 if 用于检查它是否有那么多天。斯皮克曼的方式更容易、更干净,但感谢您的回答:)
0赞 kouroubel 4/30/2022
它可能更优雅,但你怎么知道这个日期是否是现实的?有人有可能在 9 月 31 日或 2 月 30 日过生日吗?
0赞 Shruikan 4/30/2022
Normaly Time.strptime 会引发错误“日期或 strptime 格式无效”:)但是我不知道如何处理无效日期。现在我知道:)
0赞 kouroubel 4/30/2022
9月31日仍然是一个无效的日期......有点。
0赞 Shruikan 4/30/2022
这就是“rescue ArgumentError => e”的用途。它不允许保存这种日期
0赞 spickermann 4/30/2022 #2

如果您无法先验证数据库中的数字,那么我只会捕获错误并在块中处理它。peselrescue

为此,请更改

birth_date = Time.strptime("#{day}/#{month}/#{year}", '%d/%m/%Y')

if birth_date.valid?
  self.birth_date = birth_date
else
  errors.add(:pesel, I18n.t('activerecord.errors.models.profile.attributes.pesel.invalid'))
end

begin
  birth_date = Time.strptime("#{day}/#{month}/#{year}", '%d/%m/%Y')
  self.birth_date = birth_date
rescue ArgumentError => e
  errors.add(:pesel, I18n.t('activerecord.errors.models.profile.attributes.pesel.invalid'))
end

评论

0赞 Shruikan 4/30/2022
这是行不通的。我输入了“12195678915”,它保存了新的 pesel 编号,但birth_date仍然是“nil”
0赞 spickermann 4/30/2022
您是否检查了错误是否已设置?因为目前您设置了错误,而不是,所以您肯定会通过所有验证,然后填充哈希值,但仍保存记录。相反,您可能需要尝试调用此方法。before_savebefore_validationerrorbefore_validation