C4::Dates.pm - a more object-oriented replacement for Date.pm.

The core problem to address is the multiplicity of formats used by different Koha installations around the world. We needed to move away from any hard-coded values at the script level, for example in initial form values or checks for min/max date. The reason is clear when you consider string '07/01/2004'. Depending on the format, it represents July 1st (us), or January 7th (metric), or an invalid value (iso).


Arguments to new() are optional. If string_date is not supplied, the present system date is used. If date_format is not supplied, the system preference from C4::Context is used.


                my $now   = C4::Dates->new();
                my $date1 = C4::Dates->new("09-21-1989","us");
                my $date2 = C4::Dates->new("19890921    143907","sql");


The date value is stored independent of any specific format. Therefore any format can be invoked when displaying it.

                my $date = C4::Dates->new();    # say today is July 12th, 2010
                print $date->output("iso");     # prints "2010-07-12"
                print "\n";
                print $date->output("metric");  # prints "12-07-2007"

However, it is still necessary to know the format of any incoming date value (e.g., setting the value of an object with new()). Like new(), output() assumes the system preference date format unless otherwise instructed.


With no argument, format returns the object's current date_format. Otherwise it attempts to set the object format to the supplied value.

Some previously desireable functions are now unnecessary. For example, you might want a method/function to tell you whether or not a Dates.pm object is of the 'iso' type. But you can see by this example that such a test is trivial to accomplish, and not necessary to include in the module:

                sub is_iso {
                        my $self = shift;
                        return ($self->format() eq "iso");

Note: A similar function would need to be included for each format.

Instead a dependent script can retrieve the format of the object directly and decide what to do with it from there:

                my $date = C4::Dates->new();
                my $format = $date->format();
                ($format eq "iso") or do_something($date);

Or if you just want to print a given value and format, no problem:

                my $date = C4::Dates->new("1989-09-21", "iso");
                print $date->output;


                print C4::Dates->new("1989-09-21", "iso")->output;

Or even:

                print C4::Dates->new("21-09-1989", "metric")->output("iso");

"syspref" -- System Preference(s)

Perhaps you want to force data obtained in a known format to display according to the user's system preference, without necessarily knowing what that preference is. For this purpose, you can use the psuedo-format argument "syspref".

For example, to print an ISO date (from the database) in the <systempreference> format:

                my $date = C4::Dates->new($date_from_database,"iso");
                my $datestring_for_display = $date->output("syspref");
                print $datestring_for_display;

Or even:

                print C4::Dates->new($date_from_database,"iso")->output("syspref");

If you just want to know what the <systempreferece> is, you can use:



Returns the format string for DHTML Calendar Display based on date_format. If date_format is not supplied, the return is based on system preference.

                C4::Dates->DHTMLcalendar();     #  e.g., returns "%m/%d/%Y" for 'us' system preference

Error Handling

Some error handling is provided in this module, but not all. Requesting an unknown format is a fatal error (because it is programmer error, not user error, typically).

Scripts must still perform validation of user input. Attempting to set an invalid value will return 0 or undefined, so a script might check as follows:

                my $date = C4::Dates->new($input) or deal_with_it("$input didn't work");

To validate before creating a new object, use the regexp method of the class:

                $input =~ C4::Dates->regexp("iso") or deal_with_it("input ($input) invalid as iso format");
                my $date = C4::Dates->new($input,"iso");

More verose debugging messages are sent in the presence of non-zero $ENV{"DEBUG"}.


If the date format is not in <systempreference>, we should send an error back to the user. This kind of check should be centralized somewhere. Probably not here, though.

Notes: if the date in the db is null or empty, interpret null expiration to mean "never expires".