This morning I noticed the section in perlfaq4 relating to Dates. While the DateTime project has its own FAQ, I thought I'd take the time to answer the same questions, but restricting myself to the DateTime suite of modules. And in fact, to the core DateTime module where possible.
The true beauty of the DateTime suite comes in two parts: Firstly its completeness and secondly its accuracy.
DateTime has been planned from the start to be expandable. Namespaces were decided early on in the process to allow for alternate calendars (that's not even in this FAQ), formats, time zones, sets, spans and durations, events and utilities.
Accuracy was, likewise, always important. The developers have made certain to be as accurate as possible. This is the only perl module that uses the Olson Time Zone database to accurately represent time zones. Not only for today but back over 30 years. This makes it more accurate than Microsoft Windows who assume that time zones never change and that any rules that apply today must have applied throughout history.
Each of the following questions is taken from the current perlfaq4. This means it is by no means exhaustive, but that's why there's an official DateTime FAQ. The mailing list is also very active and the core developers and many others will be able to answer any other question quickly. If it's an emergency, look for me in IRC on both the Undernet or Freenode masquerading as Woosta.
Enough of a preamble, on with the show.
my $dt = DateTime->now(time_zone => 'Local');
Getting the current time in DateTime is as simple as asking for now() however, by default, DateTime will return a an object representing a floating time zone. This floating time zone has no daylight savings time and is offset from all other time zones by 0. That is, if you compare the time-of-day in a floating time zone with the same time-of-day in a fixed time zone, the difference will be 0.
If you do not need daylight-savings, or if your time zone is unknown, then floating time zones are no problem. However, if you want to me more accurate, deadly accurate, then declare your local time zone by either using 'Local' on systems that allow it, or the Olson Time Zone name such as 'Australia/Melbourne'.
$day_of_year = $dt->doy; $week_of_year = $dt->week_number;
Once you have a DateTime object there are many, many accessors that can return almost any sort of data you require.
Note that the first week of the year is defined by ISO as the one which contains the fourth day of January. Thus the 1st of January might be in the last week of the previous year. The year of the week can be retrieved with the ->week_year() function.
$century = int($dt->year / 100)+1; $millennium = int($dt->year / 1000)+1;
my $utc_dt = DateTime->now(time_zone => 'UTC'); $difference = $utc_dt - $dt;
The DateTime distribution comes with a module DateTime::Duration which accurately represents real durations. Normally in perl we subtract two epoch times to get a duration in seconds, however this may not be what we want. Due to daylight-savings, leap seconds and inequal month lengths not every unit of the callendar has the same number of seconds.
Consider subtracting August 1st from September 1st. If you do it in your head, the difference is obviously one month. However if we do it using epoch seconds, the difference is 2678400 seconds. Now if we want to use this duration anywhere else, this becomes a problem. Adding 2678400 seconds to September 1st returns October 2nd. September on has 30 days compared to August's 31.
This becomes even worse when there's a daylight-savings change during the period as our epoch will be 'out' from one month by 3600 seconds.
Once we have a duration object there are many things that can be done with it that are beyond the scope of this FAQ. See DateTime::Duration and DateTime::Format::Duration for more information.
$string = '2005-10-08T08:42'; $parser = DateTime::Format::ISO8601; $parsed_dt = $parser->parse_datetime( $string ); $epoch_seconds = $parsed_dt->epoch;
Unlike other date and time modules, DateTime has no built-in string parser. This is mainly due to the huge number of formats that could possibly be passed in. Thus there are the DateTime::Format:: modules. These modules have been specifically designed to parse and format dates and times in various formats, all using the same API.
The above code uses a string in ISO8601 format, but just by changing the parser, the same code can parse and format in any of a large range of formats. There's even glues to both Date::Manip parsing and Date::Parse parsing for when you really don't know the format.
$julian_day = $dt->jd; $modified_julian_day = $dt->mjd;
DateTime has built in accessors for both the Julian Day and the Modified Julian Day. However, as per the original FAQ, this may not be what you want. Aparently some people refer to the day-of-year as the Julian Day, please see further up this FAQ for that.
$yesterdays_date = $dt->clone(); $yesterdays_date->subtract( days => 1 );
DateTime has full support for date and time math through the ->add(), ->subtract() and ->truncate() methods. Note, however, that that these methods are destructive. If you want to keep your original object, you will need to ->clone() it first.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Data: Dates, a DateTime replacement to perlfaq4 (TZ nit)
by tye (Sage) on Oct 08, 2005 at 03:02 UTC | |
by BigLug (Chaplain) on Oct 08, 2005 at 07:00 UTC | |
by tye (Sage) on Oct 08, 2005 at 08:05 UTC | |
by BigLug (Chaplain) on Oct 09, 2005 at 07:38 UTC | |
by tye (Sage) on Oct 09, 2005 at 15:20 UTC | |
Re: Data: Dates, a DateTime replacement to perlfaq4
by brian_d_foy (Abbot) on Oct 09, 2005 at 19:10 UTC | |
Re: Data: Dates, a DateTime replacement to perlfaq4
by hakkr (Chaplain) on Oct 10, 2005 at 16:13 UTC |