Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Getting started with DateTime

by monsterzero (Monk)
on Jan 16, 2004 at 16:59 UTC ( #321831=perltutorial: 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.


Conclusion

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.

SEE ALSO

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

Credits

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

Comment on Getting started with DateTime
Select or Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perltutorial [id://321831]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (7)
As of 2014-09-22 23:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (208 votes), past polls