【问题标题】:Bug in `Date#strtime`? It parses days which more than 30/31 in a month, confusing them with the years`Date#strtime` 中的错误?它解析一个月内超过 30/31 的日子,将它们与年份混淆
【发布时间】:2019-10-29 10:17:37
【问题描述】:

为什么 strptime 方法成功解析了特定格式的日期字符串?

需要为 API 明确接受格式日期

$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
$ irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> Date.strptime('01-01-1970', '%Y-%m-%d')
=> #<Date: 0001-01-19 ((1721442j,0s,0n),+0s,2299161j)>
irb(main):003:0> Date.strptime('01-01-1970', '%Y-%m-%d').to_s
=> "0001-01-19"
irb(main):004:0> Date.strptime('01-01-1970', '%Y-%m-%d').year
=> 1
irb(main):005:0> Date.strptime('01-01-1970', '%Y-%m-%d').day
=> 19

期望:测试通过

it 'raises an exception when wrong format' do
 expect { Date.strptime('01-01-1970', '%Y-%m-%d') }.to raise_exception(ArgumentError, 'invalid format')
end

实际:expected ArgumentError with "invalid format" but nothing was raised

【问题讨论】:

  • 因为 Ruby 解析日期的方式是完全有效的,你可以通过在 repl 中运行它来展示自己。
  • @DaveNewton 你看到格式了吗? '%Y-%m-%d'perfectly valid 是什么,1970 天?
  • @maxpleaner 你读过吗?问题是:why it's happened?,而不是:how to parse string date?
  • @AlexeyStrizhak 我确实做到了。是的,因为它解析日期的方式,正如 Sergio 详细解释的那样,它将解析为有效日期。您需要使用正则表达式或更严格的日期解析机制。

标签: ruby date


【解决方案1】:

我想你有两个隐藏的问题。

为什么01%Y 的有效匹配项(意思是“年份包括世纪”)

因为为什么要假设 4 位数的年份?否则,您将无法指定 3 位数的年份(例如,882 年是基辅成为俄罗斯首都的时间)。或者在这种情况下,您确实指的是第 1 年。Ruby 不知道。

为什么1970%d 匹配?

因为这就是strptime(3) 的工作方式(它应该与之兼容)。一旦格式描述符%d ("day, 1-31") 满足19,该字符串将停止处理。

函数的返回值是一个指针,指向该函数调用中未处理的第一个字符。如果输入字符串包含的字符多于格式字符串所需的字符,则返回值指向最后一个使用的输入字符之后。

【讨论】:

  • hm...为什么Ruby 将字符串拆分并按部分分析?我的意思是,如果我提供显式格式,那么我希望在这种格式的逻辑范围内进行解析,我不知道为什么它不应该在复杂的格式中工作
  • @AlexeyStrizhak:也许您只是对格式说明符的作用或它们的严格程度有错误的期望。如果您必须拒绝您问题中的日期字符串(因为不符合您的格式),请在将其解析为日期之前使用正则表达式检查该字符串。这实际上是你在编码面试中可以看到的一个问题(我做过)。
  • 有道理。谢谢 |> 错误的期望|是的,看起来如此。老实说,我会重新阅读您的答案并尝试理解,谢谢!
  • 我没有意识到这种行为(重新开始),并且想知道为什么 Ruby 僧侣选择这样做。毕竟,如果我们要允许Date.strptime('28-03-2019', '%Y-%m-%d'),为什么假设字符串"19""20" 而不是"2" 后跟字符串"019" 的日期?此外,如果这是对格式字符串的无意反转,那么通过不引发异常,Ruby 会使编码人员更难追踪错误。您或任何人能否提出这个语言设计决策的原因?
  • @CarySwoveland:我打赌与 C 标准库的兼容性。我的意思是,如果我们要复制 printf 及其格式字符串行为,为什么要在实现上有所偏差?最小意外原则。
猜你喜欢
  • 2017-03-13
  • 2012-01-20
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 2011-08-07
相关资源
最近更新 更多