Date::Manip::Range - Parses and holds a date range


  use Date::Manip::Range;
  my $range = Date::Manip::Range->new();
  $range->parse( 'today through tomorrow' );
  $range->adjust( '3 days' );
  print $range->printf;


Date::Manip::Range parses and holds a date range. The range is defined by a start and end point. The module accepts ranges as a single string of two dates separated by a range operator. Some examples...

  my $range = Date::Manip::Range->new( {parse => 'today - tommorrow'} );
  my $range = Date::Manip::Range->new( {parse => 'Jan 21 through Feb 3'} );
  my $range = Date::Manip::Range->new( {parse => '2015-01-29 to 2015-02-03'} );
  my $range = Date::Manip::Range->new( {parse => 'from Jan 21 to Feb 3'} );
  my $range = Date::Manip::Range->new( {parse => 'between Jan 21 and Feb 3'} );

Date::Manip::Range recognizes the following range operators...


Date::Manip::Range splits the string on the operator, extracting the start and end points. It creates Date::Manip objects from those two points. The dates can be anything parsable by Date::Manip.

Important Facts

Date strings can be anything parsable by Date::Manip.
Dates must be in the correct order.
Range operators are case insensetive.
Ranges do not support times. Ranges only work on whole days.

Implicit Ranges

Date::Manip::Range supports the concept of implicit ranges. A range is implied when you pass a single time period into "parse". For example, April 2015 implies the range 2015-04-01 through 2015-04-30. Date::Manip::Range creates an implicit range when there is no range operator.

Date::Manip::Range accepts these forms of implicit ranges...


Any four digit value translates into an entire year, from January 01 through December 31.

Month YYYY

Any two part value implies a one month range from the first to the last day. For the month, you can use a number, 3 letter abbreviation, or spell out the full name.

Implicit Start and End Dates

Date::Manip::Range also recognizes implied start and end dates. This is where you give an implicit range as both the start and end, like these...

  January through March
  April 2015 - August 2015
  2014 to 2015

The start date falls on the first day of the implied range. That would be January 1 for years and the first day of the month for others.

The end date falls on the last day of the implied range. For years, that's December 31. For months, it is the last day of the month. The code correctly calculates the last day of the month - even for Februrary and leap years.

"parse" sets the "date_format" to the shortest implied range. For example, "printf" converts 2014 to May 2015 into January 2014 to May 2015. And April 2015 to May 15, 2015 becomes April 01, 2015 to May 15, 2015.



new creates a new object. You may pass default values in a hash reference. new accepts the following...


A date range in string form passed directly into the "parse" method. This allows you to initialize the object in one statement instead of two. Check the "is_valid" method and error attribute for error messages.


These attributes mark inclusive or exclusive ranges. By default, a range includes dates that fall on the start or end. For example...

  $range->new( {parse => '2015-01-15 to 2015-01-31'} );
  # returns true because the start is included
  $range->includes( '2015-01-15' );
  # retruns true because it is between the start and end
  $range->includes( '2015-01-20' );
  # retruns true because the end is included
  $range->includes( '2015-01-31' );

For exclusive ranges, set one or both of these values to false.

  $range->new( {parse => '2015-01-15 to 2015-01-31'} );
  $range->include_start( 0 );
  # returns false because the start is excluded
  $range->includes( '2015-01-15' );
  # retruns true because it is between the start and end
  $range->includes( '2015-01-20' );
  # retruns true because the end is included
  $range->includes( '2015-01-31' );


This method takes a string, parses it, and configures the Date::Manip::Range object. parse returns true on success or false for an error. Call "error" for a more specific error message.

  my $range = Date::Manip::Range->new();
  $range->parse( 'June 2014 through May 2015' );


This method moves both the start and end dates by the same amount of time. It allows you to shift an entire range.

adjust accepts a delta string suitable for Date::Manip::Delta. In addition, it you can use the following frequencies as the delta...

  • annual

    Add 1 year to both dates.

  • monthly

    Add 1 month to both dates.

  • weekly

    Add 1 week to both dates.

  • daily

    Add 1 day to both dates.

adjust returns a boolean flag indicating success. On failure, check "error" for a message.

  my $range = Date::Manip::Range( {parse => 'June 2014 to May 2015'} );
  # Add 2 months to the start and end dates.
  $range->adjust( '2 months' );
  # Displays "August 2014 to July 2015" - a two month shift.


This method returns the date range as a single string. The "format" attribute defines the resulting string. The method formates each date (start and end) using the "date_format" attribute. printf then drops those formatted dates into the string using "format".

printf accepts two optional parameters. The first parameter overrides the "date_format" attribute. The second parameter overrides the "format" attribute.

  my $range = Date::Manip::Range( {parse => 'June 2014 to May 2015'} );
  # Displays "June 2014 to May 2015".
  print $range->printf();
  # Displays "06/2014 to 05/2015".
  print $range->printf( '%m/%Y' );
  # Displays "06/2014 - 05/2015".
  print $range->printf( '%m/%Y', '%s - %s' );
  # Displays "June 2014 through May 2015".
  print $range->printf( undef, '%s through %s' );


This attributes formats the output of the "printf" method. It follows the same rules as sprintf. The format can have up to two placeholders: one for the start date and one for the end date.

Behind the scenes, the code actually calls sprintf. The start is passed as the first argument and the end date as the second.

"parse" sets format based on the appearance of the original input string. You can change format after calling "parse".

  # Default format is "%s to %s".
  my $range = Date::Manip::Range( {parse => 'June 2014 to May 2015'} );
  # Customize the format of "printf". It doesn't have to be a valid range.
  $range->format( 'starting %s until ending %s' );
  # Displays "starting June 2014 until ending May 2015".


This attribute formats the dates when you call the "printf" method. It uses the directives defined in Date::Manip::Date. Both the start and end dates use the same format.

"parse" sets date_format based on the appearance of the original input string. You can change date_format after calling "parse".

  # Default format is "%B %Y".
  my $range = Date::Manip::Range( {parse => 'June 2014 to May 2015'} );
  # Customize the dates for "printf".
  $range->date_format( '%m/%Y' );
  # Displays "06/2014 to 05/2015".


This method tells you if a given date falls within the range. A true value means that the date is inside of the range. false says that the date falls outside of the range.

The date can be a string or Date::Manip object. Strings accept any valid input for Date::Manip::Date. If the date is invalid, includes sets the "error" attribute and returns false.

Note that includes does not tell you if the date comes before or after the range. That didn't seem relevant.


This method tells you if the object holds a valid date range. Use this after calling the "new" or "parse" methods. If anything failed (invalid dates), is_valid returns false.

  if (!$range->is_valid()) { 
    print $range->error; 


Returns the last error message. This attribute can be set by the "new", "parse", "adjust", or "includes" methods. An empty string indicates no problem. You should check this value after calling one of those methods.

The object automatically clears the error message with each call to "parse", "includes", or </adjust>. That way previous errors do not make the changed object invalid.

start / end

The Date::Manip::Date objects representing the end points of the range. Note that you cannot set start or end. Use the "parse" or "adjust" methods instead.


This method signals if the object holds an implicit range. Implicit ranges occur when passing a single date value into "new" or "parse". is_implicit returns true if the range is implicit.


granularity defines the amount of time covered by an implicit range. It has a value like 1 year or 1 month or 1 day. granularity is a read-only attribute. It is set by the "new" and "parse" methods.


Date::Manip::Range only supports English range operators. Translations welcome.





Robert Wohlfarth <>


Copyright (c) 2016 Robert Wohlfarth

This module is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the full text of the licenses in the directory LICENSES.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied