系统日期为2017-02-01时,Date.parse失败

时间:2017-02-01 13:35:33

标签: ruby

我遇到了Date.parse方法的一个奇怪问题。

我尝试了几个ruby版本,它发生在所有版本中。以下测试在2.1.10版本中运行。

昨天我的所有考试都在通过,但今天他们开始失败了。原因是Date.parse调用开始引发异常。

如果系统日期是2017-01-31,它可以正常工作:

2.1.10 :002 > system('date')
Ter 31 Jan 2017 11:24:08 BRST
 => true
2.1.10 :003 > Date.parse("29%2F10%2F2015")
 => #<Date: 2017-01-29 ((2457783j,0s,0n),+0s,2299161j)>

但如果系统日期是今天,它就会失败:

2.1.10 :002 > system('date')
Qua  1 Fev 2017 11:24:27 BRST
 => true
2.1.10 :003 > Date.parse("29%2F10%2F2015")
ArgumentError: invalid date
        from (irb):3:in `parse'
        from (irb):3
        from /Users/fernando/.rvm/rubies/ruby-2.1.10/bin/irb:11:in `<main>'

我可能可以通过使用另一种方法解析这个日期来解决这个问题,但我对它今天开始失败的原因感兴趣。

2017-02-01是ruby的特殊日期吗?

4 个答案:

答案 0 :(得分:3)

Date.parse是一种尝试使用多种启发法从给定字符串解析日期的方法,以便支持许多不同的格式而不指定实际格式。因此,除非格式清晰,否则Ruby总是可能得出与您不同的结论。

为了了解Ruby如何解析您的字符串,您可以使用

Date._parse("29%2F10%2F2015")
# => {:mday=>29}

正如您所看到的,Ruby能够从传递的字符串中获取29的日期,但不会获得任何其他信息。为了形成有效日期,Ruby替换当前日期中缺少的部分。现在,自2017年2月起只有28天,结果日期在此处无效,但在1月份有效。

然而,结果并不是你真正想要的。相反,尝试首先将您的日期转换为更容易解析的字符串,然后使用Eric Duminil的方法再次尝试这个问题的另一个答案:

require 'date'
require 'uri'

string = '29%2F10%2F2015'
Date.strptime(URI.unescape(string), '%d/%m/%Y')
# => #<Date: 2015-10-29 ((2457325j,0s,0n),+0s,2299161j)>

正如您所看到的,使用Date.strptime,您可以指定已解析字符串的确切格式,因此可以确保它被正确解析或出错。

答案 1 :(得分:2)

%2F是正斜杠(/

的网址编码值

所以你需要先 decode url-encoded string

> require 'open-uri'
#=> true 
> string = "29%2F10%2F2015"
#=> "29%2F10%2F2015" 
> date = URI::decode(string)
#=> "29/10/2015" 
> Date.parse(date)
#=> #<Date: 2015-10-29 ((2457325j,0s,0n),+0s,2299161j)> 
  

2017-02-01是ruby的特殊日期吗?

不,这不是特别的;)

> s = "2017-02-01"
> Date.parse(s)
#=> #<Date: 2017-02-01 ((2457786j,0s,0n),+0s,2299161j)>

答案 2 :(得分:2)

你有三个问题:

  • '%2F'不应该在这里
  • '2017-02-01'可以是“2月1日”或“1月2日”。
  • Date.parse依赖系统日期来解析字符串。

如果你知道你有哪种格式,你真的应该使用Date.strptime

require 'date'
require 'uri'

def parse_url_date(url_date)
  Date.strptime(URI.unescape(url_date), '%d/%m/%Y')
end

puts parse_url_date("29%2F10%2F2015")
#=> 2015-10-29
puts parse_url_date("01%2F02%2F2017")
#=> 2017-02-01

答案 3 :(得分:0)

如果你知道你的日期&#34;是URL编码然后你必须首先对它们进行URL解码。使用URI.unescape(),然后将其返回的值传递给Date.parse()

Date.parse(URI.unescape("29%2F10%2F2015"))