Home > Net >  Efficient way to get closest pay day to a given date
Efficient way to get closest pay day to a given date

Time:02-08

I'm trying to figure out the most efficient way to find the closest payday from a given date.

Let's say we know payday are every 14 days and that January 6, 2022 was one of them. What is the most efficient way to find the next payday for a given date (the date is the beginning of a week actually) from a known payday?

Here is a current working ugly implementation

    def payday_first_date
      # TODO: Very reliable, but very inefficient
      @payday_first_date ||= begin
        date = known_pay_day
        date -= 14.days until date < given_date
        date  = 14.days until date > given_date
        date
      end
    end

    def known_pay_day
      # Thursday January 6, 2022 was a payday
      @known_pay_day ||= Date.new(2022, 2, 17)
    end

The given_date could be in the future and also in the past. It can be a date from another year aswell.

Thanks in advance!

CodePudding user response:

First define the known pay date and two helper methods.

require 'date'
def date_str_to_date_obj(date_str)
  DateTime.strptime(date_str, "%B %d, %Y").to_date
end
known_date = date_str_to_date_obj("January 6, 2022")
  #=> #<Date: 2022-01-06 ((2459586j,0s,0n), 0s,2299161j)>

For presentation only:

def date_obj_to_date_str(date_obj)
  date_obj.strftime("%B %d, %Y, %A")
end
date_obj_to_date_str(known_date)
  #=> "January 06, 2022, Thursday"

The main method follows.

def closest_pay_day(known_date, target_date)
  nbr_pay_dates    = (target_date - known_date)/14.0
  last_pay_date    = known_date   nbr_pay_dates.floor * 14
  next_pay_date    = last_pay_date   14
  (next_pay_date - target_date < target_date - last_pay_date) ?
  next_pay_date : last_pay_date
end

Suppose the target date is after the known pay date.

target_date_str = "March 26, 2022"

Then

target_date = date_str_to_date_obj(target_date_str)
  #=> #<Date: 2022-03-26 ((2459665j,0s,0n), 0s,2299161j)>
date_obj_to_date_str(target_date)
  #=> "March 26, 2022, Saturday"

The closest pay period to the target date is therefore

closest = closest_pay_day(known_date, target_date)
  #=> #<Date: 2022-03-31 ((2459670j,0s,0n), 0s,2299161j)>
date_obj_to_date_str(closest)
  #=> "March 31, 2022, Thursday"

which is

(target_date- closest).to_i
  #=> -5

days before the target date, meaning 5 days after the target date.


Now suppose the target date is before the known pay date.

target_date_str = "October 19, 2021"

Then

target_date = date_str_to_date_obj(target_date_str)
  #=> #<Date: 2021-10-19 ((2459507j,0s,0n), 0s,2299161j)>
date_obj_to_date_str(target_date)
  #=> "October 19, 2021, Tuesday"
date_obj_to_date_str(closest_pay_day(known_date, target_date))
  #=> "October 14, 2021, Thursday"
  •  Tags:  
  • Related