Rails Rails 新手,请教一个关于时间格式化问题

atlas · 2016年11月23日 · 最后由 suimeng 回复于 2018年02月01日 · 3578 次阅读
@appleList = Apple.find_by_sql("sql语句")

@appList是一个 apple 对象的集合,apple 对象里面有个字段 productDate 是 Date 类型,现在返回 json 数据格式

render :json => {:response => @appList}

浏览器返回

{"response":[{"productDate":"2016-11-22T00:00:00.000Z"},{"productDate":"2016-11-22T00:00:00.000Z"},{"productDate":"2016-11-22T00:00:00.000Z"},{"productDate":"2016-11-22T00:00:00.000Z"}]

现在我要返回

{"response":[{"productDate":"2016-11-22"},{"productDate":"2016-11-22"},{"productDate":"2016-11-22"},{"productDate":"2016-11-22"}]格式的数据,该如何处理?

@appleList.each{|app| app['productDate'] = app['productDate'].to_time.strftime('%Y-%m-%d')}😂

#1 楼 @winse 看样子不行,@appleList.each虽然可以改变 Date,但是这个方法 render :json => {:response => @appList}好像会自动把 Date 类型的数据显示成"2016-11-22T00:00:00.000Z"这个格式

# config/initializers/time_with_zone.rb

if defined?(::ActiveSupport)
  # ActiveSupport::JSON::Encoding.use_standard_json_time_format = false

  class ActiveSupport::TimeWithZone
    def as_json(opts = {}) # 可配置数据格式
      opts.assert_valid_keys(:date_format)
      opts[:date_format] ||= :default # 默认时间格式

      if ActiveSupport::JSON::Encoding.use_standard_json_time_format
        xmlschema(ActiveSupport::JSON::Encoding.time_precision)
      else
        self.to_s opts[:date_format]
      end
    end
  end
end

前端转换格式啊,后端返回这种是一个标准 ISO 8601,并且是带时区的

例如 JS 里面的 Moment 库就可以转换的

http://momentjs.com/

@atlas 在前端转换可能会更好,显示效果一样.

datetime.strftime('%Y-%m-%d') # date
 => "2014-09-12"
datetime.strftime('%H:%M:%S') # time
 => "16:53:18"
datetime.strftime('%Y-%m-%d %H:%M:%S') # datetime
=> "2014-09-12 16:53:18"

#2 楼 @atlas strftime() 之后变成 string 了

类似 3 楼,我搞过另一种实现方式:

module ActiveSupportJSONSerializerModifier
  def jsonify(value)
    if value.kind_of?(Time) || value.kind_of?(DateTime)
      value.strftime '%Y-%m-%d %H:%M:%S'
    else
      super value
    end
  end
end

class ActiveSupport::JSON::Encoding::JSONGemEncoder
  prepend ActiveSupportJSONSerializerModifier
end

(render json 时各种类型如何转换是由 ActiveSupport::JSON::Encoding::JSONGemEncoder#jsonify 控制的)

但这样修改会影响整个应用,如果只希望改变个别 API 的日期返回格式,还是写个辅助函数在 render 前处理一遍数据,把日期对象转为字符串吧。

比如:

def format_time_column(records, column_name)
  column_name = column_name.to_s
  # 要点是要先转成纯 Hash,否则该列依然是日期对象,依然会被 jsonify 当做日期序列化
  records.map(&:attributes).each do |record|
    record[column_name] = record[column_name].strftime('%Y-%m-%d %H:%M:%S')
  end
end

#7 楼 @bianjp 谢谢的解答,刚开始学习 rails,不懂的东西太多

#4 楼 @huacnlee 这个场景不行,提供 json api 用的

可以写在 model 里,类似这样子,

def as_json(options = {})
  hh = super(options)       
  hh[:apply_time_ymd] = self.apply_time.strftime('%Y-%m-%d')
  hh[:user_name] = User.find(self.user_id).uname
  hh[:action_flag_title] = self.action_flag == 1 ? "同意" : "不同意"
  hh
end
需要 登录 后方可回复, 如果你还没有账号请 注册新账号