从数组计算时间并转换为时区

时间:2015-12-11 23:40:14

标签: ruby-on-rails arrays ruby time average

我有一个数组bed_times,其格式为Time个实例:

bed_times = [
  Time.utc(2015, 12, 10,  5, 58, 24),
  Time.utc(2015, 12,  9,  3, 35, 28),
  Time.utc(2015, 12,  8,  6, 32, 26),
  Time.utc(2015, 12,  7,  1, 43, 28),
  Time.utc(2015, 12,  5,  7, 49, 30),
  Time.utc(2015, 12, 04,  7,  2, 30)
]
#=> [2015-12-10 05:58:24 UTC,
#    2015-12-09 03:35:28 UTC,
#    2015-12-08 06:32:26 UTC,
#    2015-12-07 01:43:28 UTC,
#    2015-12-05 07:49:30 UTC,
#    2015-12-04 07:02:30 UTC]

我想获得平均睡前时间,但我没有得到正确的结果

ave = Time.at(bed_times.map(&:to_f).inject(:+) / bed_times.size)

结果是

2015-12-07 01:26:57 -0800

这是不正确的。此外,我想将平均时间转换为不同的时区

我试过

Time.zone = 'Pacific Time (US & Canada)'
Time.zone.parse(ave.to_s)
2015-12-07 01:26:57 -0800

这也不正确。

2 个答案:

答案 0 :(得分:2)

您必须计算午夜差距的平均值

一个不优雅(但很快)的解决方案可能是:

# Keep only time    
bed_times.map! { |bt| Time.parse(bt.split(" ")[1]) }

# calculate the gap from 00:00:00
gap_from_midnight = bed_times.map do |bt|
  if bt > Time.parse("12:00:00")
    gap = (bt.to_f - Time.parse("24:00:00").to_f)
  else
    gap = (bt.to_f - Time.parse("00:00:00").to_f)
  end
  gap.to_i
end

# average in sec
avg_in_sec = gap_from_midnight.inject(:+) / bed_times.size

# average in UTC time zone 
avg = Time.at(avg_in_sec).utc # => 1970-01-01 05:26:57 UTC (result for bed_times array)

# average in PST time zone (see note)
avg_pst = Time.parse(avg.to_s).in_time_zone("Pacific Time (US & Canada)") # => Wed, 31 Dec 1969 21:26:57 PST -08:00 (result for bed_times array)

# Keep only time
avg_pst.strftime("%H:%M:%S") # => "21:26:57" (result for bed_times array)

使用bed_times数组(值为字符串)

bed_times = [
  "2015-12-10 05:58:24 UTC",
  "2015-12-09 03:35:28 UTC",
  "2015-12-08 06:32:26 UTC",
  "2015-12-07 01:43:28 UTC",
  "2015-12-05 07:49:30 UTC",
  "2015-12-04 07:02:30 UTC"
]

平均值是:

  • 05:26:57在UTC区域
  • PST区域中的
  • 21:26:57

使用另一个这样的数组

bed_times = [
  "2015-12-10 01:00:00 UTC",
  "2015-12-09 23:00:00 UTC",
  "2015-10-19 18:00:00 UTC",
]

平均值是:

  • 22:00:00在UTC区域
  • PST区域中的
  • 14:00:00

注意: .in_time_zone是来自ActiveSupport::TimeWithZone的帮手    http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html

答案 1 :(得分:0)

据我了解,您将获得一个数组arr,其中包含PST时间区域的就寝时间的UTC时间。你想计算平均就寝时间。

<强>代码

def avg_bedtime(arr)
  avg = Time.at(arr.reduce(0) do |t,s|
    lt = Time.parse(s).localtime("-08:00")
    t + Time.new(2000, 1, (lt.hour < 12) ? 2 : 1, lt.hour, lt.min, lt.sec, "-08:00").to_f
  end/arr.size)
  "%d:%d:%d" % [avg.hour, avg.min, avg.sec]
end

示例

arr = ["2015-12-10 08:58:24 UTC", "2015-12-09 03:35:28 UTC",
       "2015-12-08 06:32:26 UTC", "2015-12-07 01:43:28 UTC",
       "2015-12-05 07:49:30 UTC", "2015-12-04 07:02:30 UTC"]

我已经在这个阵列中第一次改变了它,使它更有趣。

avg_bedtime(arr)
  #=> "21:56:57"

<强>解释

让我们首先将这些字符串转换为时间对象:

utc = arr.map { |s| Time.parse(s) }
  #=> [2015-12-10 08:58:24 UTC, 2015-12-09 03:35:28 UTC, 2015-12-08 06:32:26 UTC,
  #    2015-12-07 01:43:28 UTC, 2015-12-05 07:49:30 UTC, 2015-12-04 07:02:30 UTC]

回顾PST比UTC早8小时,我们可以使用Time.localtime转换为PST:

pst = utc.map { |t| t.localtime("-08:00") }
  #=> [2015-12-10 00:58:24 -0800, 2015-12-08 19:35:28 -0800,
  #    2015-12-07 22:32:26 -0800, 2015-12-06 17:43:28 -0800,
  #    2015-12-04 23:49:30 -0800, 2015-12-03 23:02:30 -0800] 

我会在中午之前提到睡觉时间是&#34;迟到&#34;睡觉时间和当天晚些时候的早睡时间#34;就寝时间。 (这当然是武断的。例如,如果某些人是轮班工人,这可能是一个问题。)如你所见,pst的第一个元素是睡前很晚,所有其他人都是早睡

我现在将这些时间对象转换为具有相同时间但具有不同日期的时间对象。早睡前物体将被分配一个任意日期(例如,January 1, 2000),晚睡觉时间对象将在一天之后(January 2, 2000):

adj = pst.map { |t| Time.new(2000, 1, (t.hour < 12) ? 2 : 1, t.hour, t.min, t.sec, "-08:00") }
  #=> [2000-01-02 00:58:24 -0800, 2000-01-01 19:35:28 -0800, 2000-01-01 22:32:26 -0800,
 #     2000-01-01 17:43:28 -0800, 2000-01-01 23:49:30 -0800, 2000-01-01 23:02:30 -0800]

我们现在可以将时间对象转换为自纪元以来的秒数:

secs = adj.map { |t| t.to_f }
  #=> [946803504.0, 946784128.0, 946794746.0, 946777408.0, 946799370.0, 946796550.0]

计算平均值:

avg = secs.reduce(:+)/arr.size
  #=> 946792617.6666666

转换回PST区域的时间对象:

tavg = Time.at(avg)
  #=> 2000-01-01 21:56:57 -0800 

,最后,提取一天中的时间:

"%d:%d:%d" % [tavg.hour, tavg.min, tavg.sec]
  # "21:56:57