Ruby Date.strptime能否约束字符串首尾实现精确日期解析?
Ruby Date.strptime 实现严格首尾匹配的日期解析
Ruby 自带的 Date.strptime 方法没有类似正则中^和$的内置首尾约束机制,它默认只会从字符串开头匹配指定格式,忽略后续不匹配的部分,这就会出现你遇到的问题:用"%B %d, %y"解析"SEPTEMBER 8, 2016"时,方法会截断年份为两位16,结合默认规则生成日期,而非抛出异常提示格式不匹配。
要实现严格的全字符串匹配解析,可以用以下两种方法:
方法一:解析后反向验证
将解析得到的日期用相同格式重新转为字符串,和原字符串对比,若不一致则抛出异常。这种方法无需手动编写正则,通用性强:
require 'date' def strict_strptime(str, format) date = Date.strptime(str, format) unless date.strftime(format) == str raise ArgumentError, "字符串与指定格式不匹配: #{str}" end date end # 测试符合格式的情况 strict_strptime("SEPTEMBER 8, 16", "%B %d, %y") # 返回 #<Date: 2016-09-08 ...> # 测试不符合格式的情况(年份为四位) strict_strptime("SEPTEMBER 8, 2016", "%B %d, %y") # 抛出 ArgumentError
方法二:先通过正则校验格式
针对目标格式编写匹配整个字符串的正则表达式,先验证输入字符串是否完全符合格式要求,再调用strptime解析:
require 'date' def strict_strptime(str, format, full_match_regex) raise ArgumentError, "输入字符串格式不符合要求" unless str.match?(full_match_regex) Date.strptime(str, format) end # 使用示例:对应"%B %d, %y"的全匹配正则 regex = /\A[A-Za-z]+ \d{1,2}, \d{2}\z/ strict_strptime("SEPTEMBER 8, 16", "%B %d, %y", regex) # 正常解析 strict_strptime("SEPTEMBER 8, 2016", "%B %d, %y", regex) # 抛出异常
两种方法中,第一种更省心,无需额外维护正则;第二种适合需要对格式做更精细正则约束的场景。
内容的提问来源于stack exchange,提问作者lobati
相关产品推荐
相关产品推荐

