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

Ruby on rails 从数组计算时间并转换为时区,ruby-on-rails,arrays,ruby,time,average,Ruby On Rails,Arrays,Ruby,Time,Average,我有一个数组bed_times,其中包含UTC格式的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(2

我有一个数组
bed_times
,其中包含UTC格式的
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

这也不正确。

您必须计算从午夜开始的间隔的平均值

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

# 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\u时间
array(值为字符串)

平均值为:

  • 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",
]
平均值为:

  • UTC区域中的
    22:00:00
  • PST区域中的
    14:00:00
注意:
.in\u time\u zone
是来自
ActiveSupport::TimeWithZone

据我所知,您将获得一个数组
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小时,我们可以使用转换为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] 
我会把中午前的就寝时间称为“晚”就寝时间,而一天中晚些时候的就寝时间称为“早”就寝时间。(这当然是任意的。例如,如果其中一些人是轮班工人,这可能是一个问题。)正如您所看到的,
pst
的第一个元素是晚睡时间,所有其他元素都是早睡时间

我现在将这些时间对象转换为具有相同时间但不同日期的时间对象。早睡对象将被指定一个任意日期(例如,2000年1月1日),晚睡对象将被指定一天之后(2000年1月2日)

计算平均值:

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

时间=床上时间。地图!{| bt | Time.parse(bt.split(“”[1])}***NoMethodError异常:2015-12-11 05:58:24-0800的未定义方法'split':我当时尝试bt.to|s.split…但它没有拆分。我以为那是一个字符串数组。[“2015-12-10 05:58:24 UTC”、“.”、]。如果我试图从你的值创建一个时间对象,我会给出一个错误:Time.new(2015-12-10 05:58:24 UTC)SyntaxError:(irb):1:语法错误,意外的tINTEGER,预期为“')”Time.new(2015-12-10 05:58:24 UTC)如何解析时间?sleeps[1]是一个包含以下项的数组{“startTime”=>“2015-12-10T05:58:24.000Z”,“endTime”=>“2015-12-10T13:33:24.000Z”{“开始时间”=>“2015-12-09T03:35:28.000Z”,“结束时间”=>“2015-12-09T13:04:28.000Z”}然后我像这样上床睡觉的时间=睡觉[1]。映射{el | el['startTime']}。映射{el | Time.zone.parse(el.to| s)};尝试在结尾处添加谢谢。最后一件事。平均时间05:26是UTC。我想将其转换为PST。我尝试了time.zone='太平洋时间(美国和加拿大)';time.zone.parse(平均)2015-12-11 05:26:57-0800它似乎没有转换为PST
avg = secs.reduce(:+)/arr.size
  #=> 946792617.6666666
tavg = Time.at(avg)
  #=> 2000-01-01 21:56:57 -0800 
"%d:%d:%d" % [tavg.hour, tavg.min, tavg.sec]
  # "21:56:57