【问题标题】:Ruby convert time to integer and then back. Keeps adding an hourRuby 将时间转换为整数,然后再返回。不断增加一个小时
【发布时间】:2018-10-06 02:11:57
【问题描述】:

在我的 rails 应用程序中,我尝试将时间转换为整数,然后再将其转换回来。然而,当我这样做的时候,它会切换时区,把我搞砸了。

这是我的开始和停止时间表:

[8] pry(#<Campaign>)> random_schedule[0]
=> 2018-10-05 21:10:00 -0600
[9] pry(#<Campaign>)> random_schedule[1]
=> 2018-10-05 21:20:00 -0600

现在我要做的是在这些时间之间选择一个随机时间。我这样做是为了:

start = random_schedule[0].to_i
stop = random_schedule[1].to_i

selected_time = rand(start..stop)
selected_schedule = Time.at(selected_time)

但是,这会变成这样:

[1] pry(#<Campaign>)> selected_schedule
=> 2018-10-05 22:16:17 -0500

所以现在它会提前一个小时排队,尽管它应该在几分钟内发生。

我在这里做错了什么? selected_schedulerandom_schedule[0]random_schedule[1].zone 都显示为CDT,但一个是-0500,另一个是0600,所以很明显有问题。

编辑

所以我看到了一个更深层次的问题。如果我查看模型,我可以看到创建/更新时间使用 CDT,但其他字段使用 CST。这怎么可能?

=> #<campaign_schedule:0x00007fa8de3ea4e8
 id: 8,
 campaign_id: 8,
 start_date: Fri, 05 Oct 2018,
 start_time: Sat, 01 Jan 2000 22:05:00 CST -06:00,
 stop_date: Fri, 05 Oct 2018,
 stop_time: Sat, 01 Jan 2000 22:10:00 CST -06:00,
 created_at: Fri, 05 Oct 2018 21:49:46 CDT -05:00,
 updated_at: Fri, 05 Oct 2018 21:49:46 CDT -05:00>

我的表单如下所示:

<%= campaign_schedule.date_field :start_date, as: :date, value: campaign_schedule.object.try(:strftime,"%m/%d/%Y"), class: 'form-control' %>

当它保存时,它会保存为 CST,这对我来说是一个小时。

所以在一个新表单上,我在控制器中有这个,它构建了活动:

  # app/controllers/campaigns_controller.rb
  # GET /campaigns/new
  def new
    @campaign = Campaign.new
    @campaign.build_campaign_schedule.campaign_schedule_hours.build
  end

在活动表单上,它是这样的:

<%= form_with(model: @campaign, local: true, html: {role: "form", id: "campaign_form"}) do |form| %>
<div class="modal-body">
    <div class="tabs-container">
        <ul class="nav nav-tabs">
            <li class="active"><a data-toggle="tab" href="#basics"><i class="fas fa-cogs"></i> Basics</a></li>
            <li class=""><a data-toggle="tab" href="#schedule"><i class="fas fa-calendar-alt"></i> Schedule</a></li>
        </ul>
        <div class="tab-content">
            <div id="basics" class="tab-pane active">
                <div class="panel-body">
                    <%= form.fields_for :campaign_schedule do |campaign_schedule| %>
                    <div class="form-group row">
                        <div class="col-sm-5">
                            <%= label_tag "What day and time should the campaign start?" %>
                        </div>
                        <div class="col-sm-3">
                            <%= campaign_schedule.date_field :start_date, as: :date, value: Time.now.strftime("%m/%d/%Y"), class: 'form-control' %>
                        </div>
                        <div class="col-sm-3">
                            <%= campaign_schedule.time_field :start_time, as: :time, value: Time.now.strftime( "%I:%M %p"), class: "form-control" %>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<% end %>

当它保存时,这是控制器中的保存操作:

  # POST /campaigns
  # POST /campaigns.json
  def create
    @campaign = Campaign.new(campaign_params)

    respond_to do |format|
      if @campaign.save
        review_campaign_schedule
        format.html { redirect_back fallback_location: campaigns_path, notice: 'Campaign was successfully created.' }
        format.json { render :show, status: :created, location: @campaign }
      else
        format.html { render :new }
        format.json { render json: @campaign.errors, status: :unprocessable_entity }
      end
    end
  end

但是,当我返回并调用该 Campaign.start_date 时,它​​是 CST 而不是 CDT。即使我直接从 Rails 控制台执行此操作,它也使用 CST 而不是 CDT。是建筑商的事吗?看看这个:

[8] pry(#<CampaignsController>)> @campaign = Campaign.new
=> #<Campaign:0x00007fa8ef5bbab8 id: nil, name: nil, completed_date: nil, status: "Scheduled", created_at: nil, updated_at: nil>
[9] pry(#<CampaignsController>)> @campaign.build_campaign_schedule.campaign_schedule_hours.build    
=> #<CampaignscheduleHour:0x00007fa8e6377be8 id: nil, campaign_schedule_id: nil, day: nil, start_hours: nil, stop_hours: nil, created_at: nil, updated_at: nil>
[11] pry(#<CampaignsController>)> @campaign.campaign_schedule
=> #<Campaignschedule:0x00007fa8ef5b07d0 id: nil, campaign_id: nil, start_date: nil, start_time: nil, stop_date: nil, stop_time: nil, created_at: nil, updated_at: nil>
[12] pry(#<CampaignsController>)> @campaign.campaign_schedule.start_time = "22:30"
=> "22:30"
[13] pry(#<CampaignsController>)> @campaign.campaign_schedule.start_time
=> Sat, 01 Jan 2000 22:30:00 CST -06:00

【问题讨论】:

    标签: ruby-on-rails date time


    【解决方案1】:

    您从 random_schedule 开始的初始时间似乎没有考虑夏令时偏移 (DST)。你可以用random_schedule[0].dst?测试一下

    当前 CDT 时区的正确偏移量是 -0500,DST 开启:

    https://www.timeanddate.com/time/zones/cdt

    因此,当使用 Time.at(selected_time) 命令将您的时间转换回来时,它会转换为规范形式。

    【讨论】:

    • 认为我在这里发现了一个更深层次的问题。 Rails 实际上在我创建/更新的记录属性中显示 CDT,让我相信 CDT 已启用。但是,表格将日期和时间保存为 CST,这对我来说毫无意义。如果 Rails 配置了夏令时,为什么没有表单?很奇怪。
    • 不确定the forms are saving the dates and times as CST 是什么意思。也许是数据库设置?
    • 我更新了我的答案以反映 Rails 控制台的一些输出。我的模型在创建和更新时似乎都使用了正确的时区,但它的其他属性(created_at/updated_at 之外)都在 CST 而不是 CDT。希望我解释得对。
    • 如我所见,start_date 没问题,但时区问题出在start_time。你如何处理它?你能显示保存它的模板和控制器代码吗?
    • 已更新。谢谢你的帮助。希望越来越近:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    相关资源
    最近更新 更多