我有一个数组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
这也不正确。
答案 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区域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区域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