在Rails的时区困扰

bo-*_*-oz 4 datetime ruby-on-rails

我有一个使用以下配置的应用程序:

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.
  config.time_zone = 'Amsterdam'
  config.active_record.default_timezone = :utc
end
Run Code Online (Sandbox Code Playgroud)

我为用户提供了一个表单,要求一个单独的日期(日期选择器)和时间字段(下拉列表)。在before方法上,我将日期和时间连接到单个datetime字段中。似乎Time对象在某种程度上是UTC,而Date对象却不在乎。

当将其存储到数据库中时,时区会以某种方式得到纠正,但是时间会减少2个小时。这是由于时间仍在UTC上吗?我该如何以尊重日光节约的方式对此进行补偿?

代码样例

表格:

= simple_form_for @report do |f|
  .row
    .col.s6
      = f.association :report_category
    .col.s6
      = f.association :account
  .row
    .col.s6.l4
      = f.input :day, as: :string, input_html: {class: 'datepicker current-date'}
    .col.s6.l4
      = f.input :time, as: :string, input_html: {class: 'timepicker current-date'}
Run Code Online (Sandbox Code Playgroud)

模型中的回调

  def create_timestamp
    self.date = day.to_datetime + time.seconds_since_midnight.seconds
  end
Run Code Online (Sandbox Code Playgroud)

保存后,我在表单中选择的时间相差2小时。

这是创建新记录后的样子,其中时间与创建记录的时间相同,以了解两者之间的区别:

 date: Sat, 20 May 2017 16:10:00 CEST +02:00,
 created_at: Sat, 20 May 2017 14:10:33 CEST +02:00,
 updated_at: Sat, 20 May 2017 14:10:33 CEST +02:00,
 deleted_at: nil,
 time: 2000-01-01 14:10:00 UTC,
 day: Sat, 20 May 2017,
Run Code Online (Sandbox Code Playgroud)

如您所见,时间存储在UTC中,而实际上是我创建记录的14:10 CET +0200。因此,这可能会导致差异。您可以在日期中看到该日期,其中时间是created_at的+2小时。

谢谢

bln*_*lnc 5

将所有内容保留在UTC中,并消除差异。

当表单提交字段并连接DateTime对象时,它将被解释为UTC ...,因此您必须在提交信息后进行转换。

模型.rb

    # Set the Proper DateTie
    def create_timestamp
        # Create the DateTime
        date = day.to_datetime + time.seconds_since_midnight.seconds
        # Set the timezone in which you want to interpret the time
        zone = 'Amsterdam'
        # Find the offset from UTC taking into account daylight savings
        offset = DateTime.now.in_time_zone(zone).utc_offset / 3600
        # Back out the difference to find the adjusted UTC time and save it as UTC with the correct time
        self.date = date - offset.hours
    end
Run Code Online (Sandbox Code Playgroud)