15

问题

  1. 我有一个带有 Date 属性的 Ruby on Rails 模型。
  2. 在此模型的表单中,我使用带有 JQuery 日期选择器的单个文本字段来表示此属性(而不是像 Rails 自定义的那样逐年、月和日的下拉菜单)。
  3. datepicker 插入带有mm/dd/yyyy格式的日期。
  4. Rails 期待具有dd/mm/yyyy格式的日期。

例子

  • 如果用户选择March 12th, 2012,日期选择器 puts 03/12/2012,Rails 将其解释为December 3rd, 2012
  • 如果用户选择March 20th, 2012,日期选择器 puts 03/20/2012,Rails 将其解释为 2012 年第20 个月的第 3 天。由于该日期不存在,Rails 将其转换为一个nil值(我认为)。

问题

解析此日期文本字段时,如何更改 Rails 使用的日期格式?

笔记:

1)我不想更改日期选择器插入文本字段的日期格式,

2) 我不是要在视图中显示我的日期属性。

4

5 回答 5

15

我最初认为这可以通过 Rails 国际化功能来解决,但事实证明我错了。

从 Ruby 1.9 开始,日期解析的标准格式是dd/mm/yyyy,以便更好地适应国际用户。更多细节可以在这个 SO answer中找到。

该标准在 Rails 中得到维护,Date.parse现在用于处理来自表单输入的数据。使用before_validation回调不起作用,因为该字段nil将由回调方法接收。

现在有两个 gem 处理这个特定问题,即 Rails 中的日期解析不遵循I18n.locale. 两者似乎都运作良好。

  1. delocalize,由 clemens - 似乎已成功应用于相当数量的项目或项目中,并且目前拥有最多的星星。

  2. i18n_alchemy by carlosantoniodasilva - 这个最近发布了。作者是 Rails 核心团队成员,并且在这方面非常活跃。绝对值得一看。

于 2013-03-25T04:18:20.157 回答
3

由于您不想更改选择器的格式,我建议您对实际模型属性使用隐藏字段。

例如,为模型的日期属性添加一个隐藏字段,假设您像往常一样使用表单构建器:

f.hidden_field :date

然后对于选择器文本输入,不要将其绑定到模型的日期属性。假设隐藏字段的 ID 为“modelname_date”,选择器文本输入的 ID 为“date_picker”,请使用以下命令使其工作:

$(function(){
  $("#date_picker").datepicker({altField: '#nodelname_date', altFormat: 'dd/mm/yyyy'});
});

这样,日期选择器将日期显示为“mm/dd/yyyy”,但 Rails 会将日期显示为“dd/mm/yyyy”。

更新:

如果您想在 Rails 方面解决这个问题,我建议您使用另一个解决方案:

  • 向模型添加虚拟属性:attr_accessor :bad_format_date
  • 添加一个 before_validation 回调,您可以在其中解析输入日期并将其分配给真实字段:
before_validation do
  self.date = Date.strptime(bad_format_date, "%m/%d/%Y")
end

然后对于视图上的表单使用bad_format_date但用date字段值初始化它(如果它是一个编辑表单)。

于 2013-03-25T01:34:29.357 回答
0

及时性gem使 ruby​​ 日期/时间解析更加可定制,并与 Rails 很好地集成。

由于您使用的是 Rails,因此请务必查看同一个人的validates_timeliness项目。它包括 ActiveModel 的所有及时性以及复杂的日期/时间验证方法。

于 2013-03-20T18:54:44.740 回答
0

你可以尝试做这样的事情。

$(function(){
 $('#date_picker').datepicker( {
      beforeShowDay: $.datepicker.noWeekends, 
      showOtherMonths: true,
      selectOtherMonths: true,
      dateFormat: 'dd-mm-yy',
      defaultDate: date,
      gotoCurrent: true

}); 
于 2013-03-25T03:52:56.173 回答
0

我只是将以下猴子补丁添加到 config/time_formats.rb

class Date
  class << self
    alias :euro_parse :_parse
    def _parse(str,comp=false)
      str = str.to_s.strip
      if str == ''
        {}
      elsif str =~ /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{2,4})/
        year,month,day = $3.to_i,$1,$2
        date,*rest = str.split(' ')
        year += (year < 35 ? 2000 : 1900) if year < 100
        euro_parse("#{year}-#{month}-#{day} #{rest.join(' ')}",comp)
      else
        euro_parse(str,comp)
      end  
    end
  end
end
于 2013-11-15T16:16:49.063 回答