Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Finding End of Month's date

by neeraj (Scribe)
on Jan 03, 2005 at 08:28 UTC ( [id://418890]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks,
I need to find the end of month's date given a particular date / i need to check whether a particular date is end of month's date or not. i know that creating a hash of months with their end dates and of course for feb, taking into account the leap year also and matching with them will work, but i m sure there must be a CPAN module for it. Can you all point me that,
thanks in advance,
Neeraj.

Replies are listed 'Best First'.
Re: Finding End of Month's date
by ikegami (Patriarch) on Jan 03, 2005 at 09:09 UTC

    Using only modules included with Perl...

    Relative to current date:

    use Time::Local qw( timelocal_nocheck ); my @time_data; @time_data = localtime(); $time_data[4]++; # Next month. $time_data[3] = 0; # Last day of previous month. @time_data = localtime(timelocal_nocheck(@time_data)); my $year = $time_data[5]+1900; my $month = $time_data[4]+1; # Make 1-based my $last_day = $time_data[3]; printf("The last day of this month (%04d/%02d) is %d.\n", $year, $month, $last_day ); __END__ output ====== The last day of this month (2005/01) is 31.

    Relative to a specified year and month:

    use Time::Local qw( timegm_nocheck ); my $year = 2005; for my $month (1..12) { my $last_day = (gmtime(timegm_nocheck( 0, 0, 0, 1-1, # Last day of previous month. $month-1+1, # Next month (0-based). $year )))[3]; printf("The last day of %04d/%02d is %d.\n", $year, $month, $last_day ); } __END__ output ====== The last day of 2005/01 is 31. The last day of 2005/02 is 28. The last day of 2005/03 is 31. The last day of 2005/04 is 30. The last day of 2005/05 is 31. The last day of 2005/06 is 30. The last day of 2005/07 is 31. The last day of 2005/08 is 31. The last day of 2005/09 is 30. The last day of 2005/10 is 31. The last day of 2005/11 is 30. The last day of 2005/12 is 31.
Re: Finding End of Month's date
by csuhockey3 (Curate) on Jan 03, 2005 at 08:39 UTC
OT: design consideration for date ranges
by demerphq (Chancellor) on Jan 03, 2005 at 13:26 UTC

    I just thought i should mention something regarding this question. To me its probably a sign of bad design when a system requires logic to determine end of month dates (unless its a date module in of itself...)

    IME the most common reason to require an end of month date is when you have dated assignments, such as "this customer pays that rate from this date to that date". A naive DB implementation would have the start date and end date be inclusive, so an assignment for january would be Jan 1 - Jan 31. This is a problematic design for many reasons. It requires annoying code to determine the end of the month, and it makes writing queries much more difficult by introducing a bunch of weird edge cases. For instance if the From date is Jan 01 00:00:00 and the To date is Jan 31 00:00:00 what happens for the 24 hours following Jan 31? So now you have to start doing things like Jan 31 23:59:59, which is just a pain. Range queries likewise become really annoying. (To make matters even worse, its not unusual to use NULL as an end date to imply an "open assignment". This just makes queries more complex and slower.)

    A much better design IMO is to make date ranges inclusive on the from date and exclusive on the to date, in other words an interval [From,To) and require that end dates are defined (use a far future date to represent open assignments). This makes the logic much simpler. You avoid dealing with end of month dates as you can say Jan01-Feb01, you avoid dealing with time gap problems, and can reduce quite complex queries down to very simple logic. For instance to find all assignments for a particular customer for a particular time period you can say:

    select * from assignment where customer=$customer and start_date < $end_period and $start_period < end_date

    ---
    demerphq

      I actually do agree all of your post but this:
      >   To me its probably a sign of bad design when a system requires logic to determine end of month dates.
      Working for a financial institute I know of many cases where "end of month" has a business related meaning. Often dates for payments, rate-fixings etc. are set in a way like "last working date in month X".

      pelagic
Re: Finding End of Month's date
by Juerd (Abbot) on Jan 03, 2005 at 08:59 UTC

    You should pick the module and learn to use it yourself, but in general: add one day to the date; if the result is the first day of a month, the date used was obviously the last one.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: Finding End of Month's date
by TedPride (Priest) on Jan 03, 2005 at 10:33 UTC
    The following subroutine isn't a module, but it should work fine pasted anywhere in your code.
    use strict; use warnings; print monthdays('Jan',1998), "\n"; print monthdays('FEB',1999), "\n"; print monthdays('FeB',2000), "\n"; print monthdays(2,2100), "\n"; # Takes two arguments, both required: # Month - can be either numerical in the range 0-11, or alphabetic, # ignoring case. # Year - 4-digit format recommended. BEGIN { my %md_mon = ('JAN',1,'FEB',2,'MAR',3,'APR',4,'MAY',5,'JUN',6, 'JUL',7,'AUG',8,'SEP',9,'OCT',10,'NOV',11,'DEC',12); my @md_mon = (0,31,28,31,30,31,30,31,31,30,31,30,31); sub monthdays { my ($m, $y) = @_; $m = $md_mon{uc($m)} if $m =~ /[a-zA-Z]/; my $d = $md_mon[$m]; $d++ if $m == 2 && $y % 4 == 0 && ($y % 100 != 0 || $y % 400 = += 0); return $d; } }
Re: Finding End of Month's date
by brian_d_foy (Abbot) on Jan 04, 2005 at 00:03 UTC

    If you really just need the last day of the month (rather than the last business day), you might use Date::Simple. You shouldn't have to do fancy tricks with date manipulation to get a simple answer.

    use Date::Simple qw(days_in_month); my $days = days_in_month( 2004, 2 );
    --
    brian d foy <bdfoy@cpan.org>
Re: Finding End of Month's date
by Anonymous Monk on Jan 03, 2005 at 11:59 UTC
    I've always used Date::Manip for this task. Remember that the last day of a given month is the day before the first of the next month. If you give Date::Manip a date string consisting of just a month and a year, it'll assume the first of the month. So, all you need to do is advance a month, and back up a day. This can be done easily with Date::Manip, you just add a delta of "+1m -1d" (add a month, subtract a day). Then all you need to do is extract the day of the month from the resulting day. A one-liner, assuming month and year are given as arguments:
    perl -MDate::Manip -le \ 'print UnixDate DateCalc(ParseDate("@ARGV"), "+1m -1d"), "%e"'
        I'm well aware of its content.

        I'd still use Date::Manip if I were to calculate it. If it's going to be run as a time critical program, the program would either be written in C, or a lookup instead of a calculation would be used.

Re: Finding End of Month's date
by gmpassos (Priest) on Jan 05, 2005 at 23:09 UTC
    Take a look at Date::Object:
    use Date::Object ; my $d = Date::Object->new_local(2005 , 1 , 5) ; my $d_end = $d->clone->set(undef,undef,31) ; ## set(YYYY , MM , DD) print "date: $d\n" ; print "date end: $d_end\n" ; if ( $d == $d_end ) { print "Date is the last day of month!\n" ; }
    Output:
    date: 2005-01-05 00:00:00 date end: 2005-01-31 00:00:00
    Try to change the inputs for $d on new_local() to match the last day of the month. If you don't paste any argument it will get the actual time.

    Graciliano M. P.
    "Creativity is the expression of liberty".

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (7)
As of 2024-04-19 13:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found