在 rails 我需要根据日期范围获取所有记录,忽略年份
in rails i need to get all records based on a date range, ignoring the year
我正在尝试获取 rails 日期范围内的所有记录,这些记录在给定开始日期之后和给定结束日期之前,忽略年份。开始日期只有一个月。日期范围的结尾是月份和日期。
以下示例是获取雇用日期月份等于或大于一月但小于 2(二月)/ 28(天)的用户。
我正在尝试这个,但它不起作用:
users.where('extract(month from hire_date) >= ?', 1).where('extract(month from hire_date) <= ? AND extract(day from hire_date) <= ?', 2, 28)
这不起作用的原因是它会排除用户,例如 1/29 的用户,因为他们在 1 月的一天不少于 28。
有没有什么好方法可以忽略日期字段中的年份来完成这项工作?
首先让我说一下,我不熟悉 ruby-on-rails
、sql
或 activerecord
,但这个问题确实激起了我的兴趣,因为它包含许多复杂的问题我从来没有处理过。最值得注意的是:
- 如何在测试范围和目标日期可能出现的情况下适应闰年
有不同的闰年状态。
- 如何处理 2 月 29 日的聘用日期。这似乎是
与我列表中的第一项相同,但它有自己的独特之处
细微差别。
- 如何处理从一年开始然后重叠到下一年的范围。
我自己做了一些搜索,关于这个主题的信息似乎很少,尤其是任何似乎能正确处理上面列出的各种复杂性的信息,所以我决定看看我是否能想出一个我自己的逻辑方法。这似乎是一种新颖的方法,但最终我决定将 month
和 day
值转换为 float
值将允许一种简单的方法来解决闰年问题以及问题2 月 29 日,并且使用 if/else
语句和相反的布尔运算测试日期范围将解决重叠年份的范围。
您可能需要根据您的特定需求进行推断和重新配置,但这里是用纯 ruby
写出的总体思路。它相当冗长,但我这样做只是为了更清楚地说明我在做什么。我可以做得更紧凑:
hire_date = Time.new(2004, 1, 22)
provided_start_date = Time.new(2008, 12, 22)
day_value = (60*60*24) #60 seconds * 60 minutes * 24 hours = 1 day
num_days = 30
calculated_end_date = provided_start_date + num_days*day_value
start_range = provided_start_date.month + provided_start_date.day/100.0
end_range = calculated_end_date.month + calculated_end_date.day/100.0
day_float = hire_date.month + hire_date.day/100.0
if start_range < end_range
result = day_float >= start_range and day_float <= end_range
else
result = day_float >= start_range or day_float <= end_range
end
result
我会使用 to_char
将日期转换为仅包含月份和日期的字符串。例如 2021-12-31
可以翻译成 "12-31"
。然后可以将该字符串与您感兴趣的日期字符串范围进行比较。
users.where("to_char(hire_date, 'MM-DD') BETWEEN '01-01' AND '02-29'")
请注意,从理论上讲,这也会匹配无效的日期字符串,例如“01-40”。但我想可以安全地假设具有有效日期的 to_char
永远不会 return 这样的无效日期字符串。
所以我想出了一些对此有用的东西。
给定以下内容:
start_date = 01 Jan 2021
end_date = 02 Feb 2021
Users.where("(extract(month from hire_date) * 100 + extract(day from hire_date)) BETWEEN ? AND ?", ((start_date.month * 100) + start_date.day), ((end_date.month * 100) + end_date.day))
开始日期和结束日期可以是任何日期,这应该可以让所有用户介于两者之间,因为 SQL 介于两者之间是包容性的,它也会让结束和开始日期落在开始/结束日期之间的用户日期,忽略年份。
我正在尝试获取 rails 日期范围内的所有记录,这些记录在给定开始日期之后和给定结束日期之前,忽略年份。开始日期只有一个月。日期范围的结尾是月份和日期。 以下示例是获取雇用日期月份等于或大于一月但小于 2(二月)/ 28(天)的用户。 我正在尝试这个,但它不起作用:
users.where('extract(month from hire_date) >= ?', 1).where('extract(month from hire_date) <= ? AND extract(day from hire_date) <= ?', 2, 28)
这不起作用的原因是它会排除用户,例如 1/29 的用户,因为他们在 1 月的一天不少于 28。
有没有什么好方法可以忽略日期字段中的年份来完成这项工作?
首先让我说一下,我不熟悉 ruby-on-rails
、sql
或 activerecord
,但这个问题确实激起了我的兴趣,因为它包含许多复杂的问题我从来没有处理过。最值得注意的是:
- 如何在测试范围和目标日期可能出现的情况下适应闰年 有不同的闰年状态。
- 如何处理 2 月 29 日的聘用日期。这似乎是 与我列表中的第一项相同,但它有自己的独特之处 细微差别。
- 如何处理从一年开始然后重叠到下一年的范围。
我自己做了一些搜索,关于这个主题的信息似乎很少,尤其是任何似乎能正确处理上面列出的各种复杂性的信息,所以我决定看看我是否能想出一个我自己的逻辑方法。这似乎是一种新颖的方法,但最终我决定将 month
和 day
值转换为 float
值将允许一种简单的方法来解决闰年问题以及问题2 月 29 日,并且使用 if/else
语句和相反的布尔运算测试日期范围将解决重叠年份的范围。
您可能需要根据您的特定需求进行推断和重新配置,但这里是用纯 ruby
写出的总体思路。它相当冗长,但我这样做只是为了更清楚地说明我在做什么。我可以做得更紧凑:
hire_date = Time.new(2004, 1, 22)
provided_start_date = Time.new(2008, 12, 22)
day_value = (60*60*24) #60 seconds * 60 minutes * 24 hours = 1 day
num_days = 30
calculated_end_date = provided_start_date + num_days*day_value
start_range = provided_start_date.month + provided_start_date.day/100.0
end_range = calculated_end_date.month + calculated_end_date.day/100.0
day_float = hire_date.month + hire_date.day/100.0
if start_range < end_range
result = day_float >= start_range and day_float <= end_range
else
result = day_float >= start_range or day_float <= end_range
end
result
我会使用 to_char
将日期转换为仅包含月份和日期的字符串。例如 2021-12-31
可以翻译成 "12-31"
。然后可以将该字符串与您感兴趣的日期字符串范围进行比较。
users.where("to_char(hire_date, 'MM-DD') BETWEEN '01-01' AND '02-29'")
请注意,从理论上讲,这也会匹配无效的日期字符串,例如“01-40”。但我想可以安全地假设具有有效日期的 to_char
永远不会 return 这样的无效日期字符串。
所以我想出了一些对此有用的东西。 给定以下内容:
start_date = 01 Jan 2021
end_date = 02 Feb 2021
Users.where("(extract(month from hire_date) * 100 + extract(day from hire_date)) BETWEEN ? AND ?", ((start_date.month * 100) + start_date.day), ((end_date.month * 100) + end_date.day))
开始日期和结束日期可以是任何日期,这应该可以让所有用户介于两者之间,因为 SQL 介于两者之间是包容性的,它也会让结束和开始日期落在开始/结束日期之间的用户日期,忽略年份。