packetstormer has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks

Could anyone point me in the right direction to calculate the number of seconds between two dates, taking into consideration weekends, holidays and the working day (9-5:30)?

I have been looking at Data:Calc and Date::Calendar to figure out the days between two working days. However, I need it figure out how it make it more exact. For example, a start time of Friday @4:33pm to end time of the following Wednesday @5:10pm. I was hoping the former two libraries might have a "to_epoch" routine but no such luck

Suggestions would be most welcome!!

Replies are listed 'Best First'.
Re: Calculate seconds between dates
by ikegami (Patriarch) on Nov 23, 2017 at 22:45 UTC
    # We assume $dt1 and $dt2 are during working hours, and # we assume that DST changes will never occur during working hours, so # we can ignore time zones. use DateTime::Format::RFC3339 qw( ); my $format = DateTime::Format::Strptime->new( format => '%Y-%m-%dT%H:%M:%S', time_zone => 'floating', on_error => 'croak', ); my $dt1 = $format->parse_datetime('2017-11-17T16:00:00'); my $dt2 = $format->parse_datetime('2017-11-22T17:10:00'); my $total = 0; if (is_workday($dt1)) { ( my $eod = $dt1->clone() ) ->set( hour => 17, minute => 30, second => 0, nanosecond => 0 ); $total += $eod->delta_ms($dt1)->in_units('seconds') if $eod > $dt1; } if (is_workday($dt2)) { ( my $sod = $dt2->clone() ) ->set( hour => 9, minute => 0, second => 0, nanosecond => 0 ); $total += $sod->delta_ms($dt2)->in_units('seconds') if $sod < $dt2; } $dt1->truncate( to => 'day' ); $dt2->truncate( to => 'day' ); while (1) { $dt1->add( days => 1 ); last if $dt1 >= $dt2; next if !is_workday($dt1); $total += 8.5 * 60; }
Re: Calculate seconds between dates
by thanos1983 (Parson) on Nov 24, 2017 at 23:13 UTC

    Hello packetstormer,

    An alternative solution to your problem could be to the use of Date::Manip module.

    The module is very very powerful and with simple use of ""business" you can choose to only calculate the days that are business days and not holidays/weekends.

    Business day for the module is considered 08:00am - 05:00pm (9 hours / 1 hour lunch). Sample of code below:

    #!/usr/bin/perl use strict; use warnings; use Date::Manip; my $date_1 = "November 24 2017 4:59pm"; my $date_2 = "November 27 2017 08:01am"; my $sec = Delta_Format(DateCalc($date_1, $date_2, "business"), 0, "%st +"); printf "diff secs: %d\n", $sec; __END__ $ perl sample.pl diff secs: 120

    More information regarding the functions you can find here Date::Manip::DM5. If for any reason you want to change the hours/days you can do it through Date::Manip::Config/BUSINESS CONFIGURATION VARIABLES.

    Update: Adding the Mode "business" explanation. The third parameter that you can add on the DateCalc function is $mode. This parameter when you do date calculations can take 6 different options. Sample from the documentation:

    exact : an exact, non-business calculation semi : a semi-exact, non-business calculation approx : an approximate, non-business calculation business : an exact, business calculation bsemi : a semi-exact, business calculation bapprox : an approximate, business calculation

    For more information you can read the official documentation Date::Manip::Calc/MODE.

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Calculate seconds between dates
by Your Mother (Archbishop) on Nov 23, 2017 at 22:14 UTC

    There are probably four main options from Date::Calc, Time::Piece, DateTime, and Date::Manip. Here's one of them off the top of my head for tomorrow (Friday) to next Wednesday at the times you suggested‐ Update: not working time here, so definitely not what you want though Mktime is a to_epoch routine.

    perl -MDate::Calc=Mktime -E 'say abs Mktime(2017,11,24,16,33,0) - Mkti +me(2017,11,29,17,10,0)' 434220

      They want the number of working seconds.

Re: Calculate seconds between dates
by Anonymous Monk on Nov 24, 2017 at 13:59 UTC
    Any one of several date/time packages (including those that are built in to the core) will provide you with the inclusive number of days between two dates, which is the starting point. Some will even handle holidays and weekends for you, but if not it's still relatively easy. In every case, the first and the last whatever-it-is (day, week ...) are the ones that require special consideration. If you do find a package that will handle the days for you, then all that remains is to calculate the relevant portion of the first day and of the last one. And some of that is up-to-you: for instance, what if the ending-time was 6:00 pm?