mm/dd/yyyy
格式插入日期。dd/mm/yyyy
格式的日期。03/12/2012
,Rails 将其解释为 2012 年 12 月 3 日。03/20/2012
,Rails 将其解释为 2012 年 20 月 的第 3 天。由于该日期不存在,Rails 会将其转换为nil
价值(我认为)。如何更改 Rails 在解析此日期文本字段时使用的日期格式?
备注:
1)我不想更改日期选择器插入文本字段的日期格式,
2)我不是在询问在视图中显示我的日期属性。
我最初认为这可以通过 Rails 国际化功能来解决,但事实证明我错了。
从Ruby 1.9开始,日期解析的标准格式是
dd/mm/yyyy
,以便更好地适应国际用户。更多详细信息可以在这个SO答案中找到。
该标准在 Rails 中得到维护,因为
Date.parse
现在用于处理来自表单输入的数据。使用 before_validation
回调不起作用,因为该字段将被回调方法接收为 nil
。
现在有两个 gem 处理这个特定问题,即 Rails 中的日期解析不遵循
I18n.locale
中的区域设置。两者似乎都运作良好。
delocalize,作者:clemens - 似乎已在相当多的项目中成功应用,并且目前拥有最多的星星。
i18n_alchemy by carlosantoniodasilva - 这个最近发布了。作者是 Rails 核心团队成员,并且是一名非常活跃的成员。绝对值得一看。
由于您不想更改选择器的格式,我建议您对实际模型属性使用隐藏字段。
例如,假设您照常使用表单生成器,为模型的日期属性添加隐藏字段:
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 do
self.date = Date.strptime(bad_format_date, "%m/%d/%Y")
end
然后对于视图上的表单使用
bad_format_date
但使用 date
字段值初始化它(如果它是编辑表单)。
及时性 gem 使 ruby 日期/时间解析更加可定制,并且与 Rails 很好地集成。
由于您正在使用 Rails,请务必查看同一个人的validates_timeiness 项目。它包括 ActiveModel 的所有及时性以及复杂的日期/时间验证方法。
$(function(){
$('#date_picker').datepicker( {
beforeShowDay: $.datepicker.noWeekends,
showOtherMonths: true,
selectOtherMonths: true,
dateFormat: 'dd-mm-yy',
defaultDate: date,
gotoCurrent: true
});
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
为我们提供了属性API,它允许我们使用自定义行为定义模型属性类型。在本例中,我们需要一个常规的旧 :date
,但在转换应用程序值以在数据库查询中使用时进行特殊处理。我们可以像这样定义新属性:
# in lib/types/mdy_date.rb
class MDYDate < ActiveRecord::Type::Date
MDY_FORMAT = /(\d{2})\/(\d{2})\/(\d{4})/
MDY_SWAP = '\\2/\\1/\\3'
def cast(value)
if value.is_a?(::String) && value.match?(MDY_FORMAT)
# swap day and month so Ruby's Date._parse reads it correctly
super(value.gsub(MDY_FORMAT, MDY_SWAP))
else
super
end
end
end
# in config/initializers/types.rb
ActiveRecord::Type.register(:mdy_date, MDYDate)
# in models/your_model.rb
attribute :date_field, :mdy_date
# This will now return records where date_field
# is 2024-06-07 (June 7), rather than 2024-07-06 (July 6),
# but otherwise behaves like and is serialized to Date
YourModel.where(date_field: '06/07/2024')