【问题标题】:Create Active Model datetime with Epoch Timestamps使用 Epoch 时间戳创建活动模型日期时间
【发布时间】:2014-09-23 17:45:57
【问题描述】:

我有一个移动应用程序,它可以通过使用SimpleEvent 模型的标准路由向我们的 Rails 应用程序发送 Post 请求来创建事件。模型的重要部分在模式中如下所示:

create_table "simple_events", force: true do |t|
    t.datetime "start_date",   null: false
    t.datetime "end_date",     null: false
end

应用程序发送浮点值来指示时间是最简单的,因为这是它们在本地存储的方式。但是,当我尝试使用带有以下行的纪元时间戳在 Rails 控制台中创建 SimpleEvent 时:

SimpleEvent.create("start_date"=> 1406815132.0, "end_date"=> 1406815132.0)

我收到此错误:

ArgumentError: argument out of range
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/values/time_zone.rb:289:in `initialize'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/values/time_zone.rb:289:in `new'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/values/time_zone.rb:289:in `parse'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/core_ext/string/zones.rb:9:in `in_time_zone'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/attribute_methods/time_zone_conversion.rb:37:in `start_date='
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/attribute_assignment.rb:45:in `public_send'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/attribute_assignment.rb:45:in `_assign_attribute'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/attribute_assignment.rb:32:in `block in assign_attributes'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/attribute_assignment.rb:26:in `each'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/attribute_assignment.rb:26:in `assign_attributes'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/core.rb:455:in `init_attributes'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/core.rb:198:in `initialize'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/inheritance.rb:30:in `new'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/inheritance.rb:30:in `new'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/persistence.rb:33:in `create'
    from (irb):71
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/console.rb:90:in `start'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/console.rb:9:in `start'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/commands_tasks.rb:69:in `console'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
    from /Users/ataylor/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'2.1.1 :072 >

我尝试在 rails 源代码中寻找可能的解释,但运气不佳。我可以做些什么来允许从模型中的时间戳创建 DateTimes?

【问题讨论】:

    标签: ruby-on-rails ruby datetime activerecord epoch


    【解决方案1】:

    如果您仍然希望能够将start_dateend_date 与正常时间对象或字符串一起使用,我将创建几个新方法来从时间字符串设置 start_date/end_date:

    class SimpleEvent < ActiveRecord::Base
      def start_ts=(ts)
        write_attribute :start_date, DateTime.strptime(ts.to_s, '%s')
      end
    
      def end_ts=(ts)
        write_attribute :end_date, DateTime.strptime(ts.to_s, '%s')
      end
    end
    

    使用它们:

    SimpleEvent.create("start_ts"=>"1406815132.0", "end_ts"=>"1406815132.0")
    

    现在,当您使用 start_ts/end_ts 方法创建 SimpleEvent 时,它将解析时间戳并适当地设置 start_date/end_date。

    【讨论】:

    • 我真的很喜欢这个解决方案,但不幸的是它似乎对我不起作用。我添加了attr_accessor :start_tsattr_accessor :end_ts 以消除此错误:ActiveRecord::UnknownAttributeError: unknown attribute: start_ts 但它仍然没有保存,而是执行回滚并且生成的SimpleEvent 对象对于start_dateend_date 属性具有nil。我错过了什么吗?
    • 抱歉,我忘记在方法名称中添加=。我正在使用正确的方法名称更新我的答案。
    • 谢谢!那很完美。时间必须以数字格式发送,而不是像我将更新的原始问题中的字符串,而且我根本不需要 attr_accessor 行,与您的回答一致。
    • @kujenga,我将更新我的答案以将ts 处理为字符串、整数或浮点数。
    【解决方案2】:

    我建议通过添加一个额外的函数将它转换为日期时间并存储来保存日期时间。

    class SimpleEvent < ActiveRecord::Base
    
      def self.save_time start_time, end_time
          self.create(start_time: Time.at(start_time).to_datetime, end_time: Time.at(end_time).to_datetime
      end
    end
    

    我们关心在模型本身中编写一个函数,以便我们可以将数据作为纪元时间本身读取。

    class SimpleEvent < ActiveRecord::Base
    
       def started_at
          self.start_time.to_i
       end
    
       def end_at
          self.end_time.to_i
       end
    end 
    

    【讨论】:

      猜你喜欢
      • 2017-03-23
      • 2015-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 1970-01-01
      • 2017-09-01
      • 1970-01-01
      相关资源
      最近更新 更多