简体   繁体   中英

Order date on day and month

I have users with a birth_date and now I want to query all users who have their birthday within the next 10 days. I can't just order on birth_date because then I will get this:

01-01-1960
18-12-1975
16-12-1998

Instead of the desired result:

16-12-1998
18-12-1975
01-01-1960

So how can I only order on the day and month, but not the year?

This works in postgreSQL...

start_month = Date.today.month
start_day = Date.today.day
end_month = (Date.today + 10).month
end_day = (Date.today + 10).day

if start_month == end_month
    @users = User.where("DATE_PART('month', birth_date) = ? AND DATE_PART('day', birth_date) >= ? AND DATE_PART('day', birth_date) <= ?", start_month, start_day, end_day)
else
    @users = User.where("(DATE_PART('month', birth_date) = ? AND DATE_PART('day', birth_date) >= ?) OR (DATE_PART('month', birth_date) = ? AND DATE_PART('day', birth_date) <= ?)", start_month, start_day, end_month, end_day)
end
@users.order("DATE_PART('month', birth_date), DATE_PART('day', birth_date)")

This selects all records with birthdays within the next 10 days and sorts them.

If ten days in the future is still the same month (say on December 14) it selects December between 14 and 24... if it's in a future month (say on December 25) it selects December to end of month and January from beginning to the 4th.

A ruby implementation. Note that it may not be as performant as the DB version...

ids_of_next_10_days = User.all.pluck(:id, :birth_date).map do |user_info|
  next_birthday = user_info[1].change(year: Time.now.year) 
  next_birthday = next_birthday.change(year: Time.now.year + 1) if next_birthday < Date.today
  next_birthday.between?(Date.today, Date.today + 10) ? user_info[0] : nil
end.compact

User.where(id: ids_of_next_10_days)

On the Ruby side you can select needed users at first(Postgresql to_char is used):

today = Date.current
dates = (today ... today + 10.days).map { |d| d.strftime('%m%d') }
dates << '0229' if dates.include?('0228') # update by SteveTurczyn
users = User.where("to_char(birth_date, 'MMDD') in (?)", dates).to_a

then sort them:

users.sort_by! do |user|
  user_yday = user.birth_date.yday
  user_yday >= today.yday ? user_yday : user_yday + 366
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM