Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

The DateTime suite of modules was created to address a very fundimential problem with dates in perl. There are several different packages on CPAN with overlapping functionality, but it was difficult to take dates in one package and convert them to another which you would often have to do to get a function from a different package.The primary goal of DateTime is to solve this problem. The DateTime project also has the Olson Time Zone database support built in. This database contains code and data that represent the history of local time for many locations around the globe. It is updated to reflect changes made by political bodies to UTC offsets and daylight-saving rules. This database is used by several implementations, including the GNU C Library used in GNU/Linux.

Currently the project can be divided into several categories.

Core functionality - This contains the core datetime object along with time zone handling. In addition there are modules that handle various types of datetime sets, and preforming set math operations on them.

Parsing and formatting - This set contains the modules that help getting
dates into and out of datetime.

Events and sets - This contains various modules that are based on generating an event or set of events. Events can be any event like easter sunrise/sunset.

Non-Gregorian calenders - This contains the modules for converting dates to/from other
calenders like Julian, Mayan and others.

Using DateTime

Let's take a look at how we can use DateTime to create a date in perl. Having downloaded it from CPAN and installed it in the normal manner using it is as simple as:

use strict; use warnings; use DateTime; my $dt1 = DateTime->new( year => 2003, month => 8, day => 20, hour => 0, minute => 0, second => 0, );

Or since you most often want the current date and/or time you can simply do

my $dt2 = DateTime->now(time_zone=>'local'); my $dt3 = DateTime->today(time_zone=>'local');

The difference between the to is that DateTime->now not only has the date but also the time. whereas DateTime->today is truncated to the day. Both of these will take the time zone offset. On some operating systems (windows) setting the time_zone param to local will not work unless the TZ environment variable is set.

Now that I have something in DateTime how can I get it out? DateTime provides some basic output routines. Some examples are

print $dt1->ymd('-'); # produces 2003-08-20 print $dt1->mdy('-'); # produces 08-20-2003 print $dt1->datetime(); # produces 2003-08-20T00:00:00

The outputs are self explanatory except for the DateTime() method. The output is like 2003-08-20T00:00:00. I mainly use this for debugging and testing purposes.

Converting between timezones is what makes DateTime shine.

my $dt1 = DateTime->new( year => 2003, month => 8, day => 26, hour => 21, time_zone => 'America/Chicago' );

What time is it in Helsinki, when it is 9pm in Chicago?

$dt2 = $dt1->clone->set_time_zone( 'Europe/Helsinki' ); print $dt2->datetime, "\n";

One of the big problems with handling dates is daylight savings time. Since DateTime used the Olson database, DateTime can do it all for you.

my $dt1 = DateTime-> new ( year =>'1998', month =>'4', day =>'4', hour =>'21', time_zone =>'local' ); $dt1->add(hours =>10); print $dt1->datetime ,"\n";

This will print 1998-04-05T08:00:00. Notice that the time is 8:00 not 7:00 this is because on April 5 1998 at 2:00 am is when daylight savings time takes effect here in Los Angeles. DateTime is smart enough to know the DST rules and makes the correction.

But what if I have a date that is outside of my program (external source) well there are currently 14 formatting/parsing modules available to datetime. Chances are one of them will parse the date for you. Here is an example.

use strict; use warnings; use DateTime::Format::HTTP; my $date = 'Mon, Feb 3 04:00:00 GMT 2003'; my $dt_class = 'DateTime::Format::HTTP'; my $dt = $dt_class->parse_datetime($date); print $dt_class->format_datetime($dt);

In this example I have chosen to use the DateTime::Format::HTTP module created by Iain Truskett. Basicly, I have a date (in HTTP format) and I use the parse_datetime method to convert the string to a datetime object. Then I output the date in GMT ASCII time format. One thing to notice is that the formatting modules all have a parse_datetime (for getting strings into) and format_datetime (for outputting DT objects) methods. This makes it easy to use all of the formatting modules since they all have a some what standard interface.

This is all fine and good but what happens when you do not know the format of the date. Well the other day someone came to comp.lang.perl.misc and asked a very similer question. He asked:

Hello, I just came from cpan, after doing some searches and before I get a module, wanted to ask if any one out there knows of a module that takes an array of dates and sort them regardless of the date format.

Good question!! lets see if Datetime can help with this. I checked the DateTime FAQ and came up with something like this.

use strict; use warnings; use DateTime; my @new_dates; my @dates =(``Sat, 19 Jul 2003 15:53:45 -0500'', ``1996-02-03'',``08-Feb-1998 14:15:29 GMT'', ``19850411'', ``1985-04-12'', ``1985-04'', ``18 Feb 2003 06:54:23 -0000'', ``+001999-04-12'', ``01 Jan 2003 07:03:06 -0000'', ``1982-102'', ``21 Mar 2001 09:15:32 -0800'', ``06 Jan 2002 10:08:00 -0000'', ``09 Jan 2003 11:32:40 -0500'', ); foreach my $new_date (@dates) { push(@new_dates,DateTime::Format::Mytest->parse_datetime($new_date +) );} print map {$_->datetime(), ``\n''} sort @new_dates; package DateTime::Format::Mytest; use DateTime::Format::HTTP; use DateTime::Format::Mail; use DateTime::Format::ISO8601; use DateTime::Format::Builder ( parsers => { parse_datetime => [ sub { eval { DateTime::Format::HTTP->parse_datetime($_[1] ) } }, sub { eval { DateTime::Format::Mail->parse_datetime($_[1] ) } }, sub { eval { DateTime::Format::ISO8601->parse_datetime( $_[1]) } }, ] } );
Now the OP did not specify what format his dates were in so I just had to make some up. In the above example the real workhorse is in the package DateTime::Format::Mytest, what I have done is chain together three different DateTime format modules in order to parse the dates. Once I parsed the dates (and placed them in the new_dates array) I just sorted the new array using the standard sort function.

Ok, now that I can create a date let's look at how to compare 2 different dates. In DateTime we can use the compare method for this.

Here is an example:

my $dt = DateTime-> new(year => 2002, month=> 8, ); my dt2 = DateTime->new(year => 2003, month=> 2, ); my $cmp = DateTime->compare($dt, $dt2);

This will set the $cmp variable to either -1,0 or 1. If $dt is less than $dt2 the value of $cmp will be -1. If $dt is equal to $dt2 the value will be 0 and if $dt is greater than $dt2 the value will be 1. As you can see this is using the built in function compare. You can also use the standard perl function to accomplish the same thing.

if ($dt > $dt2) {do ....;} elsif($dt == $dt2) {do something else;} elsif($dt < $dt2) {do still something else...;}

All of these work as expected!

Date math is very easy with DateTime.Here is an example.

my $dt1 = DateTime->now(); my $dt2 = $dt1->clone->subtract( weeks => 1);

This will produce a date one week earler. I can use days, months, years and all work as expected.


The DateTime project is still being developed. However, I have found it to be extreamly useful. It has made dealing with date and times in perl much simpler.


For more information about the datetime project please see the website There is also a mailing list. You can subscribe by sending a message to


Major thanks goes to Dave Rolsky for writing the DateTime module and to the rest of the developers at the datetime project.

In reply to Getting started with DateTime by monsterzero

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others browsing the Monastery: (3)
    As of 2018-05-27 03:54 GMT
    Find Nodes?
      Voting Booth?