如何在Rails中移除日期数组中指定时段外的元素?
问题:筛选Datetime数组中的指定时间段元素
需求说明
通过以下Ruby代码生成包含连续Datetime元素的数组(最多覆盖62天,每30分钟一个元素):
start_date = (Date.today + 10.hours + 30.minutes).to_datetime end_date = (Date.today + 1.day + 18.hours).to_datetime period = 0.5/24 array = start_date.step(end_date, period).to_a
需要移除数组中所有处于每天00:00至10:29,以及18:00至当天结束的Datetime元素,最终只保留每天10:30到18:00之间的元素。
原代码问题分析
你尝试的代码返回nil,核心问题有两个:
- 字符串比较时间逻辑错误:用
strftime('%k:%M:%S')转换后的字符串做between?判断,会因字符串字典序逻辑导致时间判断失效;且w_start_time、w_end_time基于start_date偏移计算,没有针对每个元素的当天时间做判断,完全偏离需求。 reject!的返回特性:reject!是破坏性方法,会直接修改原数组;当数组中没有符合条件的元素被移除时,它会返回nil而非修改后的数组。建议用非破坏性方法select或reject生成新数组。
解决方案
直接针对每个Datetime元素的时分数值做判断,筛选符合时间范围的元素,以下是两种简洁可靠的实现:
方法1:直接判断时分
filtered_array = array.select do |dt| hour = dt.hour minute = dt.min # 筛选10:30及以后、18:00及以前的时间 (hour > 10 || (hour == 10 && minute >= 30)) && (hour < 18 || (hour == 18 && minute == 0)) end
方法2:转换为当天总分钟数判断
将时间转换为当天的总分钟数,用区间判断更直观:
filtered_array = array.select do |dt| daily_total_minutes = dt.hour * 60 + dt.min # 10:30对应630分钟,18:00对应1080分钟 (630..1080).include?(daily_total_minutes) end
两种方法都能准确筛选目标时间段元素,且不受数组覆盖天数限制,逻辑清晰可靠。
内容的提问来源于stack exchange,提问作者Codrin
相关产品推荐
相关产品推荐

