解析月份过多的日期

时间:2016-02-19 09:33:09

标签: ruby-on-rails ruby date

有没有办法正确解析月中有太多天数的日期? E.g。

  • '2016-01-32' = '2016-02-01'
  • '2015-12-32' = '2016-01-01'

这是为了支持我的一些基于JS的前端的简单日期操作。

这是Ruby 2.3.0和Rails 4.2.5。我认为这是在早期版本中工作 - 也许解析规则收紧了?

我宁愿依赖标准库,也不是闰年等知识,而不是自己实现。

4 个答案:

答案 0 :(得分:2)

require 'date'

y, m, d = '2016-01-32'.split('-').map(&:to_i)
# => [2016, 01, 32]

last_day_of_month = Date.civil(y, m, -1)
# => #<Date: 2016-01-31 ((2457419j,0s,0n),+0s,2299161j)>

date = last_day_of_month + (d - last_day_of_month.day)
# => #<Date: 2016-02-01 ((2457420j,0s,0n),+0s,2299161j)>

答案 1 :(得分:2)

您可以使用Date::_parse(或Date::_iso8601)解析日期字符串而无需验证:

require 'date'

h = Date._parse('2016-01-32')
#=> {:mday=>32, :year=>2016, :mon=>1}

使用Simone Carletti's suggestion创建日期实例:

Date.new(h[:year], h[:mon]).next_day(h[:mday] - 1)
#=> #<Date: 2016-02-01 ...>

如果日期和月份都超出范围,您可以使用:

h = Date._parse('2016-14-32')
#=> {:mday=>32, :year=>2016, :mon=>14}

Date.new(h[:year]).next_month(h[:mon] - 1).next_day(h[:mday] - 1)
#=> #<Date: 2017-03-04 ...>

next_daynext_month分别相当于+<<,因此最后一行也可以写为:

Date.new(h[:year]) << (h[:mon] - 1) + (h[:mday] - 1)

或:

Date.new(h[:year]) << h[:mon].pred + h[:mday].pred

答案 2 :(得分:0)

尝试解析与您提到的日期相似的日期会引发错误

DateTime.parse('2016-01-32')
ArgumentError: invalid date

一种可能的解决方案是为日期解析创建自定义函数/类。您将解析转发到DateTime对象,如果失败并出现该错误,您可以通过剥离日期编号并将其替换为1来重试。

如果成功,则将剩余天数添加到日期。

date = DateTime.parse('2016-01-1')
 => Fri, 01 Jan 2016 00:00:00 +0000
date + (32-1).days
 => Mon, 01 Feb 2016 00:00:00 +0000

现有的核心或Rails库都不会自动为您执行此操作。因此,您需要一个自定义功能。

您应该能够按照上面的说明和示例轻松编写方法。

答案 3 :(得分:0)

这是一种方法:

require 'date'

date_string = '2016-01-50' 

year,month,day =  date_string.split('-').map(&:to_i)

date = Date.new(year,month)

(day-1).times{date = date.next}

p date #=> 2016-02-19