Ruby strtime不';t在%Y/%m/%d上使用参数';2017年1月25日&x27;
今天发现了一些奇怪的行为,我希望有人能解释一下 我正在使用strtime验证导入文件中的日期。在这种情况下,如果文件中的一行包含不符合格式%Y/%m/%d(2017/01/25)的日期,我想抛出一个错误 我调用strtime如下:Ruby strtime不';t在%Y/%m/%d上使用参数';2017年1月25日&x27;,ruby,date,strptime,Ruby,Date,Strptime,今天发现了一些奇怪的行为,我希望有人能解释一下 我正在使用strtime验证导入文件中的日期。在这种情况下,如果文件中的一行包含不符合格式%Y/%m/%d(2017/01/25)的日期,我想抛出一个错误 我调用strtime如下: Date.strptime('25/01/2017', '%Y/%m/%d') 我预计这将失败,因为25个不符合今年的标准。但是,此操作成功,提供的日期为: 0025,01,20 如果我在(2018年1月25日)前后交换月和日,它将失败,因为它确实检测到该月无效 那
Date.strptime('25/01/2017', '%Y/%m/%d')
我预计这将失败,因为25个不符合今年的标准。但是,此操作成功,提供的日期为:
0025,01,20
如果我在(2018年1月25日)前后交换月和日,它将失败,因为它确实检测到该月无效
那么是什么原因呢?这似乎很奇怪,它不仅创造了这一精神面貌的年份(0025年),而且更疯狂的是,它无视从字符串末尾开始的“17”而没有问题
提前感谢!:) 你必须思考你实际上说了什么:
Date.strptime('25/01/2017', '%Y/%m/%d')
你是说你想要年0025
,月01
和日20
(它去掉了其余部分)。最后你会得到0025-01-20
您不能仅仅依靠Date.strtime
为您进行验证
最好是通过regexp实际解析它并进行验证
对于您的格式,可能的regexp(一种简单的方法):
在您的情况下,您将得到nil
,因为它不匹配
如果您获得匹配,您将获得:
#
问题在于,这不会检查日期的正确格式。您仍然需要检查strtime
是否可以解析结果(如Tom Lord提供的链接中的)
另一方面,您也可以仅使用regexp进行检查,这可能相当复杂:(以下regex检查yyyy/mm/dd
格式):
然后,您就可以立即知道日期的格式是否正确,并且不必使用strtime
检查解析日期
编辑:
处理时间问题时,请记住始终执行自己的检查!不要依赖于功能。时间的问题是,你有很多例外,甚至你有一个ISO 8601,也许其他一些应用程序可能不遵循它
根据评论,我想更深入地挖掘strtime
现在我想将注释粘贴到源代码中(在date_s_strtime函数和data_core.c中):
/*
*电话号码:
*Date.strtime([string='-4712-01-01'[,format='%F'[,start=Date::意大利语]]])->Date
*
*使用给定的
*模板,并创建一个日期对象。strtime不支持
*与strftime不同的标志和宽度规范。
*
*日期.strtime('2001-02-03','%Y-%m-%d')#=>#
*日期.strtime('03-02-2001','%d-%m-%Y')#=>#
*日期.strtime('2001-034','%Y-%j')#=>#
*日期.strtime('2001-W05-6','%G-W%V-%u')#=>#
*Date.strtime('2001 04 6','%Y%U%w')#=>#
*Date.strtime('2001 05 6','%Y%W%u')#=>#
*Date.strtime('sat3feb01','%a%d%b%y')#=>#
*
*另见strtime(3)和#strftime。
*/
您可以看到类似sat/feb的字符串也被使用,因此解析器可以处理字符串也就不足为奇了待继续-深入研究C代码2017-->-->20似乎是一种更通用的方法:始终忽略任何尾随字符。您可以执行
Date.strtime('25/01/20 BLA BLA BLA','%Y/%m/%d')
并得到相同的结果。至于为什么25
被解释为0025
,而不是错误,我无法理解。根据我的理解,%Y
至少需要4位数字才能有效,但显然不是这样。可能是一个bug?你可能会在中找到与你的问题相关且有帮助的答案。我最终进行了最初的正则表达式检查,然后是striptime。正如Tom Lord所说,我希望%Y在第一个正斜杠之前有4个字符,这对我来说是一个公平的假设。它的实际工作方式似乎与文档中描述它的方式背道而驰。@MathewBarnard请参阅我的第一次编辑。当我开始的时候,我会发布更多关于C代码细节的信息。现在,请参阅注释,其中说明了有关此函数的很多内容。
'25/01/2017'.match(/\d{4}\/\d{2}\/\d{2}/)
^(?:(?:(?:(?:(?:[1-9]\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:[2468][048]|[13579][26])00))(\/)(?:0?2\1(?:29)))|(?:(?:[1-9]\d{3})(\/)(?:(?:(?:0?[13578]|1[02])\2(?:31))|(?:(?:0?[13-9]|1[0-2])\2(?:29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\2(?:0?[1-9]|1\d|2[0-8])))))$
/*
* call-seq:
* Date.strptime([string='-4712-01-01'[, format='%F'[, start=Date::ITALY]]]) -> date
*
* Parses the given representation of date and time with the given
* template, and creates a date object. strptime does not support
* specification of flags and width unlike strftime.
*
* Date.strptime('2001-02-03', '%Y-%m-%d') #=> #<Date: 2001-02-03 ...>
* Date.strptime('03-02-2001', '%d-%m-%Y') #=> #<Date: 2001-02-03 ...>
* Date.strptime('2001-034', '%Y-%j') #=> #<Date: 2001-02-03 ...>
* Date.strptime('2001-W05-6', '%G-W%V-%u') #=> #<Date: 2001-02-03 ...>
* Date.strptime('2001 04 6', '%Y %U %w') #=> #<Date: 2001-02-03 ...>
* Date.strptime('2001 05 6', '%Y %W %u') #=> #<Date: 2001-02-03 ...>
* Date.strptime('sat3feb01', '%a%d%b%y') #=> #<Date: 2001-02-03 ...>
*
* See also strptime(3) and #strftime.
*/