NAME
DateTimeX::Period - Provides safe methods to get start and end of period in all timezones.
VERSION
This document describes DateTimeX::Period version 0.02
SYNOPSIS
# Optionally get local timezone
use DateTime::TimeZone qw();
my $timezone = DateTime::TimeZone->new( name => 'local' )->name();
use DateTimeX::Period qw();
my $dt = DateTimeX::Period->now(
time_zone => $timezone,
);
my $interval_start = $dt->get_start('month');
my $interval_end = $dt->get_end('month');
DESCRIPTION
DateTimeX::Period is a subclass of DateTime & provides easy yet safe methods to work in period context such as a day for all timezones.
It is recommended practise to work in UTC and switch to specific timezones only when needed. IF YOU CAN DO SO, THEN THIS MODULE IS NOT FOR YOU!!!
Yet sometimes this is not possible and this module can help you. It works around such problems like:
1. Assume you want to get start of the month, it's convenient to use truncate() available in DateTime, however this would throw an error:
use DateTime;
my $dt = DateTime->new(
year => 2011,
month => 4,
day => 2,
time_zone => 'Asia/Amman'
);
$dt->truncate(to => 'month'); # Runtime error
Q: You might have guessed, what did I do wrong? A: Well time between 00:00 - 00:59 01/04/2011 in 'Asia/Amman' did not exist. There are cases when you can't truncate to weeks, days or even hours! ( see unit tests ).
2. Assume your client that lives in 'America/Goose_Bay' is running your app and today is 13/03/2010 00:05, and your app for whatever reason adds a day:
use DateTime;
my $dt = DateTime->new(
year =>2010,
month => 3,
day => 13,
minute => 5,
time_zone => 'America/Goose_Bay',
);
$dt->add(days => 1); # Runtime error!
Q: What's wrong now? A: 14/03/2010 00:05 in 'America/Goose_Bay' did not exist!
3. Assume you are running critical application that needs to get epoch! Conveniently DateTime has epoch() and for whatever reasons you need to perform some operations, such as these: use DateTime; my $dt = DateTime->new( year=> 2013, month => 10, day => 26, hour => 23, minute => 59, second => 59, time_zone => 'Atlantic/Azores', ); $dt->add( seconds => 1 ); # 2013-10-27T00:00:00 same print $dt->epoch(); # 1382832000 diff!!! $dt->truncate(to => 'hour'); # 2013-10-27T00:00:00 same print $dt->epoch(); # 1382835600 diff!!!
Q: Why epoch() returns different epoch time when local time doesn't change? A: It so happens that 00:00 occurred twice! DateTime documentation classify this as ambiguous and always returns later date! Whereas get_start('hour') from DateTimeX::Period ( i.e. this module ), would have returned correct epoch: use DateTimeX::Period; my $dt = DateTime::Period->new( year=> 2013, month => 10, day => 26, hour => 23, minute => 59, second => 59, time_zone => 'Atlantic/Azores', ); $dt->add( seconds => 1 ); # 2013-10-27T00:00:00 same print $dt->epoch(); # 1382832000 same $dt->get_start('hour'); # 2013-10-27T00:00:00 same print $dt->epoch(); # 1382832000 same
All in all, this is convenient and safe module to play with when you can't use UTC time. It is great solution for such case as following: $user cannot use more than $threshold of something within a day in his local time or within your operating timezone. Hence query database using its APIs to get $user's $threshold so far and react upon: pretended_api_call_GET_DATA( from => $dt->get_start('day')->epoch(), to => $dt->get_end('day')->epoch(), );
METHODS
get_start($period)
Returns DateTime object with the start of the given period.
The start date/time depends in which context period is provided: - if it's a day, than midnight of that day - if it's a week, than Monday at midnight of that week - if it's a month, than 1st day at midnight of that month - and etc.
get_end($period)
Returns DateTime object with end of the given period, which is same as start of the next period.
The end date/time depends in which context period is provided: - if it's a day, than midnight of the next day - if it's a week, than Monday at midnight of the following week - if it's a month, than 1st day at midnight of the following month - and etc.
In cases where midnight does not exist, the start of those periods are not at midnight, but this should not affect the end of the period, which is the same as the start of the next period. if it happens to be not at midnight, which might happen in case of 'day', 'week' or 'month' try to truncate, if it fails gracefully fallback to another algorithm.
get_period_keys()
Returns all period keys in preserved order.
get_period_label($key)
Returns period label.
CAVEATS
Start of the week is always Monday.
BUGS
Please report any bugs or feature requests to https://github.com/vytas-dauksa/DateTimeX-Period/issues.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc DateTimeX::Period
ACKNOWLEDGEMENTS
This module has been written by Vytas Dauksa <vytas.dauksa@smoothwall.net>.
COPYRIGHT AND LICENSE
Copyright (C) 2014, Smoothwall.
This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.