Subject: | Wishlist, patched: add ability to fetch week_number and week_year for locales with specified first_day_of_week |
Our weeks start on a Saturday (don't ask), I've created a locale class
overriding first_day_of_week, like so:
sub first_day_of_week {6}
I assumed this would then change the numbers generated by
week/week_number/week_year, but that didn't seem to be the case.
The code below can just be added to DateTime somewhere to provide local_
equivalents of the week number methods, returning the local numbers. As
commented, it might be able to be optimised a little bit, I'm not quite
clear on exactly what some of the maths is doing, to substitute the
local first day of week. I guess it may also be worth adding some
additional options in some of the formatting stuff, although you don't
seem to have many letters left.
sub local_week {
my $self = shift;
unless ( defined $self->{local_c}{local_week_year} ) {
my $jan_one_dow_m1
# This algorithm was taken from Date::Calc's DateCalc.c file
#= ( ( $self->_ymd2rd( $self->year, 1, 1 ) + 6 ) % 7 );
#Work out how the above needs translating to use the local
day, reinterpreted based on Date::Calc::PP's DateCalc_Week_Number
= ( ( DateTime->new(year => $self->year, month => 1, day =>
1, locale => $self->locale())->local_day_of_week() ) - 1);
$self->{local_c}{local_week_number}
= int( ( ( $self->{local_c}{day_of_year} - 1 ) +
$jan_one_dow_m1 ) / 7 );
$self->{local_c}{local_week_number}++ if $jan_one_dow_m1 < 4;
if ( $self->{local_c}{local_week_number} == 0 ) {
$self->{local_c}{local_week_year} = $self->year - 1;
$self->{local_c}{local_week_number}
= $self->_local_weeks_in_year(
$self->{local_c}{local_week_year} );
}
elsif ($self->{local_c}{local_week_number} == 53
&& $self->_local_weeks_in_year( $self->year ) == 52 ) {
$self->{local_c}{local_week_number} = 1;
$self->{local_c}{local_week_year} = $self->year + 1;
}
else {
$self->{local_c}{local_week_year} = $self->year;
}
}
return @{ $self->{local_c} }{ 'local_week_year', 'local_week_number' };
}
sub _local_weeks_in_year
{
my $self = shift;
my $year = shift;
#TODO: Later versions of DateTime optimise _weeks_in_year this is
copied from to something involving leap years and start days
#Possibly adapt that to include this optimisation
my $jan_one_dow =
#TODO: Older DateTime's have this as the presumably optimised (
( $self->_ymd2rd( $year, 1, 1 ) + 6 ) % 7 ) + 1;
#Work out how that needs translating to use the local day
( DateTime->new(year => $year, month => 1, day => 1, locale =>
$self->locale())->local_day_of_week() );
my $dec_31_dow =
#TODO: Older DateTime's have this as the presumably optimised (
( $self->_ymd2rd( $year, 12, 31 ) + 6 ) % 7 ) + 1;
#Work out how that needs translating to use the local day
( DateTime->new(year => $year, month => 12, day => 31, locale =>
$self->locale())->local_day_of_week() );
return $jan_one_dow == 4 || $dec_31_dow == 4 ? 53 : 52;
}
sub local_week_year { ( $_[0]->local_week )[0] }
sub local_week_number { ( $_[0]->local_week )[1] }