Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: Calculating Number Of Pay Periods (UPDATED)

by thanos1983 (Parson)
on Oct 09, 2017 at 10:27 UTC ( [id://1200980]=note: print w/replies, xml ) Need Help??


in reply to Calculating Number Of Pay Periods

Hello Anonymous Monk,

Something "similar" has been asked before How to find business days?.

But also to point out that there is a beautiful module Date::Manip that contains a function called Date::Manip::Recur. There also some examples provided Date::Manip::Examples/RECURRING EVENTS which can retrieve the frequency from until specified date.

The beauty of this module is that you can change days, months, years, timezone(s) more or less what ever comes to your mind and you will get what you want.

Update For better and more accurate calculation use it like this:

my $start = ParseDate('now'); my $end = "2017123123:59:59"; # Instead of my ($start, $end) = qw(2017-01-01 2017-12-31);

Sample of code:

#!/usr/bin/perl use strict; use warnings; use Date::Manip; use feature 'say'; my ($start, $end) = qw(2017-01-01 2017-12-31); # y:m:w:d:h:m:s my @days = ParseRecur('0:0:0:1:0:0:0', $start, $start, $end); my @weeks = ParseRecur('0:0:1::0:0:0', $start, $start, $end); my @months = ParseRecur('0:1:0::0:0:0', $start, $start, $end); my @years = ParseRecur('1:0:0::0:0:0', $start, $start, $end); my @datesEvery15th = ParseRecur('0:0:0:15:0:0:0', $start, $start, $end +); say "Number of days: " . scalar @days; say "Number of weeks: " . scalar @weeks; say "Number of months: " . scalar @months; say "Number of years: " . scalar @years; say "Number of payments: " . scalar @datesEvery15th; =print payment dates for my $date (@dates15th) { say UnixDate($date, "%Y-%m-%d"); } =cut __END__ $ perl test.pl Number of days: 365 Number of weeks: 53 Number of months: 12 Number of years: 1 Number of payments: 25

Update2: To find out if the payment day is a working day or it will be shifted to the next working day. Read the POD for more information Date::Manip::DM5:

for my $date (@datesEvery15th) { if (Date_IsWorkDay($date)) { say UnixDate($date, "%Y-%m-%d"); } else { my $nearestWorkingData = Date_NearestWorkDay($date); say UnixDate($nearestWorkingData, "%Y-%m-%d"); } } __END__ 2017-10-09 2017-10-24 2017-11-08 2017-11-23 2017-12-08 2017-12-22

Update3: An alternative way to know the exact time from today to what ever day you want that can easily be updated based on timezone. Sample of code below:

#!/usr/bin/perl use strict; use warnings; use Date::Manip; use feature 'say'; use Data::Dumper; my $dateLocal = ParseDate('now'); # say $dateLocal; my $end = "2017123123:59:59"; my $dateStartLocal = ParseDate($dateLocal); my $dateEnd = ParseDate($end); my $deltaLocal = DateCalc( $dateStartLocal, $dateEnd, 1 ); say $deltaLocal; my @dataLocal = split(/:/, $deltaLocal); my @values = qw(year(s) month(s) week(s) day(s) hour(s) minute(s)); my %hashLocal; @hashLocal{@values} = @dataLocal; print Dumper \%hashLocal; ###### Different Timezone(s) ###### # From timeZone To timeZone my $dateTimeZone = Date_ConvTZ($dateLocal,"GMT","CST"); my $dateStartTimezone = ParseDate($dateLocal); my $deltaTimezone = DateCalc( $dateStartTimezone, $dateEnd, 1 ); say $deltaTimezone; my @dataTimezone = split(/:/, $deltaTimezone); my %hashTinezone; @hashTinezone{@values} = @dataTimezone; print Dumper \%hashTinezone; __END__ $ perl test.pl 0:2:3:1:9:13:31 $VAR1 = { 'week(s)' => '3', 'month(s)' => '2', 'minute(s)' => '13', 'hour(s)' => '9', 'day(s)' => '1', 'year(s)' => '0' }; 0:2:3:1:9:13:31 $VAR1 = { 'year(s)' => '0', 'day(s)' => '1', 'minute(s)' => '13', 'hour(s)' => '9', 'week(s)' => '3', 'month(s)' => '2' };

Hope this helps, BR.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re^2: Calculating Number Of Pay Periods
by 1nickt (Canon) on Oct 09, 2017 at 11:59 UTC

    53 weeks in a year?


    The way forward always starts with a minimal test.

      Yes. The year is 365-366 days, depending, whereas weeks are 7 days (where 52 weeks is only 364 days: not a full year). Businesses often use "work weeks", and every once in a while, there is a "leap-week", to get the calendar back in sync, so the first work week of a year re-aligns with the start of the business's fiscal or calendar year. See more at ISO_week_date and ISO_8601.

        Yes, calenders have some strange rules. Our common Gregorian calendar has a lot of legacy, e.g. the short february that has to be compensated by making other months longer. 12 months of 30 days each are obviously too short, leaving five or six days that have to be spread over the 12 months. Easy for leap years, choose every even or odd month. In non-leap years, remove the extra day from one of the months.

        J. R. R. Tolkien had different ideas for Middle-earth. The stories of Middle-earth are fictional history for our real planet, so Middle-earth calendars also work for planet earth. The Shire calendar, used by the Hobbits, splits the year into 12 months of 30 days each. The remaining five or six days are not assigned to a month, they stay outside of the months. The year is split into two halves. Each of the halves is wrapped in two day of the remaining days. The middle of the year is marked by the fifth remaining day, and in case of a leap year, the leap day is inserted afther the mid-year's day. So there are two days outside the months in winter, when the year is incremented (compare to New Year's Eve and New Year) and three or four days in summer (no equivalent). A clever trick is that the mid-year's day and the leap day are not assigned a week day. This way, only 364 days are assigned a weekday, and because 364 is a multiple of seven, each year starts with the same weekday, and therefore, every day of the year has a fixed weekday.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
        Or depending on which flavor of weirdness you like, you can use a 360-day calendar.

      Yup, if the year starts on a thursday (if you use ISO reckoning).

      365 days are 52 weeks + 1 day. Every 6 years or so, you have 7 of these remaining days, and they, too, belong to a certain year…

      Hello 1nickt,

      You are right the year has 52 weeks and 1 or 2 day(s) depending upon the number of days in the year.

      Sample of calculation on calendar common year 365 days:

      1 common year = 365 days = (365 days) / (7 days/week) = 52.143 weeks = + 52 weeks + 1 day

      Sample of calculation on leap year has 366 days, when February has 29 days:

      1 leap year = 366 days = (366 days) / (7 days/week) = 52.286 weeks = 5 +2 weeks + 2 days

      I was counting the remaining days as a week. So the solution is to remove the last input and count in total the remaining weeks:

      Sample bellow before and after:

      #!/usr/bin/perl use strict; use warnings; use Date::Manip; use Data::Dumper; my ($start, $end) = qw(2017-01-01 2017-12-31); # y:m:w:d:h:m:s my @weeks = ParseRecur('0:0:1::0:0:0', $start, $start, $end); print Dumper \@weeks; =sample $VAR1 = [ '2017010100:00:00', '2017010800:00:00', '2017011500:00:00', '2017012200:00:00', . . . '2017121700:00:00', '2017122400:00:00', '2017123100:00:00' # Not a week (remaining days) ]; =cut pop @weeks; say "Number of weeks: " . scalar @weeks; print Dumper \@weeks; =output $VAR1 = [ '2017010100:00:00', '2017010800:00:00', '2017011500:00:00', '2017012200:00:00', . . . '2017121000:00:00', '2017121700:00:00', '2017122400:00:00' # Last week on 2017 ]; =cut

      BR / Thanos

      Seeking for Perl wisdom...on the process of learning...not there...yet!

        For the OP, weeks are not relevant (FWIW, I'd countcalculate months, double that number, and check for partial months at beginning and end of the concerning period).

        If payment were weekly, however, and retirement more than 6 years away, you would want to keep the correct amount of those additional weeks - or countcalculate "paydays" (Mondays, or whatever) which might start at a date different from January 1st, anyway.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1200980]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-26 09:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found