Reputation: 951
I am trying to write a payroll program and one of the payment methods is twice a month (the 15th and 30th and/or 31st). I am able to get the payment dates for the current month, but I need to get them printed for the following year. My code thus far is:
require "active_support/core_ext"
require 'date'
def twice_a_month_payment_schedule
middle_of_month = Date.today.at_end_of_month - 15
end_of_month = Date.today.at_end_of_month
one_year = Date.today.at_end_of_month + 365
starting_payment_date = Date.parse(start_date) ### start_date is an argument in the format of "%Y-%m-%d".
while starting_payment_date < one_year
if middle_of_month.saturday?
middle_of_month - 1
elsif middle_of_month.sunday?
middle_of_month - 2
elsif end_of_month.saturday?
end_of_month - 1
elsif end_of_month.sunday?
end_of_month - 2
end
starting_payment_date += 1
end
pay_dates << middle_of_month.strftime("%m-%d-%Y")
pay_dates << end_of_month.strftime("%m-%d-%Y")
pay_dates
end
Any advice would be appreciated!
Thanks
Upvotes: 1
Views: 1396
Reputation: 110675
This is a comment, not an answer. I wanted to point out a small problem with your code and also suggest how you can organize it a little better. I've taken @Nick's code and made a few changes.
I understand you do not want paydays to fall on weekends. Therefore, instead of:
if middle_of_month.saturday?
middle_of_month - 1
elsif middle_of_month.sunday?
middle_of_month - 2
elsif end_of_month.saturday?
end_of_month - 1
elsif end_of_month.sunday?
end_of_month - 2
end
you want:
if middle_of_month.saturday?
middle_of_month - 1
elsif middle_of_month.sunday?
middle_of_month - 2
end
if end_of_month.saturday?
end_of_month - 1
elsif end_of_month.sunday?
end_of_month - 2
end
As it stands, if both paydays initially fall on a weekend, only the mid-month payday will be changed. With this modification, the operations for each payday are nearly the same, so it makes sense to eliminate the repetitive bits. Here's how you might do it:
require "active_support/core_ext"
require 'date'
def twice_a_month_payment_schedule(year, month)
base = Date.new(year, month)
[check_and_format_payday(base+14),
check_and_format_payday(base.at_end_of_month)]
end
def check_and_format_payday(payday)
case
when payday.saturday?
payday -= 1
when payday.sunday?
payday -= 2
end
payday.strftime("%a %m-%d-%Y")
end
puts "Jan 2014: #{twice_a_month_payment_schedule(2014, 1)}"
# Jan 2014: ["Wed 01-15-2014", "Fri 01-31-2014"]
"Feb 2014: #{twice_a_month_payment_schedule(2014, 2)}"
# Feb 2014: ["Fri 02-14-2014", "Fri 02-28-2014"]
"Mar 2014: #{twice_a_month_payment_schedule(2014, 3)}"
# Mar 2014: ["Fri 03-14-2014", "Mon 03-31-2014"]
puts "Aug 2014: #{twice_a_month_payment_schedule(2014, 8)}"
# Aug 2014: ["Fri 08-15-2014", "Fri 08-29-2014"]
puts "May 2015: #{twice_a_month_payment_schedule(2015, 5)}"
# May 2015: ["Fri 05-15-2015", "Fri 05-29-2015"]
puts "Feb 2024: #{twice_a_month_payment_schedule(2024, 2)}"
# Feb 2024: ["Thu 02-15-2024", "Thu 02-29-2024"]
puts "Dec 2135: #{twice_a_month_payment_schedule(2135, 12)}"
# Dec 2135: ["Thu 12-15-2135", "Fri 12-30-2135"]
Notice that I changed the output format slightly to include the day-of-week.
require "active_support/core_ext"
is only needed for the method at_end_of_month
. You could alternatively define it yourself:
class Date
def at_end_of_month
next_month - 1
end
end
Upvotes: 1
Reputation: 23939
Why not generalize the helper to get the dates for any year/month:
require "active_support/core_ext"
require 'date'
def twice_a_month_payment_schedule(year, month)
base = Date.new(year, month)
middle_of_month = 14.days.since(base)
end_of_month = base.at_end_of_month
if middle_of_month.saturday?
middle_of_month - 1
elsif middle_of_month.sunday?
middle_of_month - 2
elsif end_of_month.saturday?
end_of_month - 1
elsif end_of_month.sunday?
end_of_month - 2
end
[middle_of_month.strftime("%m-%d-%Y"), end_of_month.strftime("%m-%d-%Y")]
end
puts "Jan 2014: #{twice_a_month_payment_schedule(2014, 1)}"
puts "Mar 2014: #{twice_a_month_payment_schedule(2014, 3)}"
puts "Aug 2014: #{twice_a_month_payment_schedule(2014, 8)}"
puts "May 2015: #{twice_a_month_payment_schedule(2015, 5)}"
puts "Feb 2024: #{twice_a_month_payment_schedule(2024, 2)}"
puts "Dec 2135: #{twice_a_month_payment_schedule(2135, 12)}"
Results:
⚡️ ruby derp.rb
Jan 2014: ["01-15-2014", "01-31-2014"]
Mar 2014: ["03-15-2014", "03-31-2014"]
Aug 2014: ["08-15-2014", "08-31-2014"]
May 2015: ["05-15-2015", "05-31-2015"]
Feb 2024: ["02-15-2024", "02-29-2024"]
Dec 2135: ["12-15-2135", "12-31-2135"]
Upvotes: 2