root/branches/release-26/lib/MT/DateTime.pm @ 1174

Revision 1174, 4.6 kB (checked in by bchoate, 23 months ago)

Updated copyright year for source.

  • Property svn:keywords set to Author Date Id Revision
Line 
1# Movable Type (r) Open Source (C) 2001-2008 Six Apart, Ltd.
2# This program is distributed under the terms of the
3# GNU General Public License, version 2.
4#
5# $Id$
6
7# Adapted from DateTime package to avoid requirement of DateTime package.
8
9package MT::DateTime;
10
11use Exporter;
12@MT::DateTime::ISA = qw( Exporter );
13use vars qw( @EXPORT_OK );
14@EXPORT_OK = qw( ymd2rd tz_offset_as_seconds );
15
16sub new {
17    my $class = shift;
18    my (%param) = @_;
19    my $self = \%param;
20    bless $self, $class || __PACKAGE__;
21}
22
23sub week_year { (shift->week)[0] }
24sub week_number { (shift->week)[1] }
25
26sub year { shift->{year} }
27sub month { shift->{month} }
28sub day { shift->{day} }
29sub hour { shift->{hour} }
30sub minute { shift->{minute} }
31sub second { shift->{second} }
32sub time_zone { shift->{time_zone} }
33
34sub day_of_year {
35    my $self = shift;
36    return $self->{local_c}{day_of_year} if $self->{local_c}{day_of_year};
37
38    my $year = $self->year;
39    my $days = 0;
40
41    require MT::Util;
42    for (my $i = 1; $i < $self->month; $i++) {
43        $days += MT::Util::days_in($i, $year);
44    }
45    $days += $self->day;
46    $self->{local_c}{day_of_year} = $days;
47}
48
49sub week {
50    my $self = shift;
51
52    unless ( defined $self->{local_c}{week_year} ) {
53        my $jan_one_dow_m1 =
54            ( ( $self->ymd2rd( $self->year, 1, 1 ) + 6 ) % 7 );
55
56        $self->{local_c}{week_number} =
57            int( ( ( $self->day_of_year) + $jan_one_dow_m1 ) / 7 );
58        $self->{local_c}{week_number}++ if $jan_one_dow_m1 < 4;
59
60        if ( $self->{local_c}{week_number} == 0 ) {
61            $self->{local_c}{week_year} = $self->year - 1;
62            $self->{local_c}{week_number} =
63                $self->weeks_in_year( $self->{local_c}{week_year} );
64        }
65        elsif ( $self->{local_c}{week_number} == 53 &&
66                $self->weeks_in_year( $self->year ) == 52 )
67        {
68            $self->{local_c}{week_number} = 1;
69            $self->{local_c}{week_year} = $self->year + 1;
70        }
71        else
72        {
73            $self->{local_c}{week_year} = $self->year;
74        }
75    }
76
77    return @{ $self->{local_c} }{ 'week_year', 'week_number' }
78}
79
80sub weeks_in_year {
81    my $self = shift;
82    my $year = shift;
83   
84    my $jan_one_dow =
85        ( ( $self->ymd2rd( $year, 1, 1 ) + 6 ) % 7 ) + 1;
86    my $dec_31_dow =
87        ( ( $self->ymd2rd( $year, 12, 31 ) + 6 ) % 7 ) + 1;
88
89    return $jan_one_dow == 4 || $dec_31_dow == 4 ? 53 : 52;
90}
91
92sub ymd2rd {
93    my $self = shift;
94
95    use integer;
96    my ( $y, $m, $d );
97    if (@_) {
98        ( $y, $m, $d ) = @_;
99    } elsif (ref $self) {
100        ( $y, $m, $d ) = ( $self->{year}, $self->{month}, $self->{day} );
101    }
102
103    my $adj;
104
105    # make month in range 3..14 (treat Jan & Feb as months 13..14 of
106    # prev year)
107    if ( $m <= 2 )
108    {
109        $y -= ( $adj = ( 14 - $m ) / 12 );
110        $m += 12 * $adj;
111    }
112    elsif ( $m > 14 )
113    {
114        $y += ( $adj = ( $m - 3 ) / 12 );
115        $m -= 12 * $adj;
116    }
117
118    # make year positive (oh, for a use integer 'sane_div'!)
119    if ( $y < 0 )
120    {
121        $d -= 146097 * ( $adj = ( 399 - $y ) / 400 );
122        $y += 400 * $adj;
123    }
124
125    # add: day of month, days of previous 0-11 month period that began
126    # w/March, days of previous 0-399 year period that began w/March
127    # of a 400-multiple year), days of any 400-year periods before
128    # that, and 306 days to adjust from Mar 1, year 0-relative to Jan
129    # 1, year 1-relative (whew)
130
131    $d += ( $m * 367 - 1094 ) / 12 + $y % 100 * 1461 / 4 +
132          ( $y / 100 * 36524 + $y / 400 ) - 306;
133}
134
135sub tz_offset_as_seconds {   
136    my $self = shift;
137    my $offset = shift; 
138    if (ref $self) {
139        $offset = $self->{time_zone};
140    }
141
142    return undef unless defined $offset;
143
144    return 0 if $offset eq '0';
145       
146    my ( $sign, $hours, $minutes, $seconds );
147    if ( $offset =~ /^([\+\-])?(\d\d?):(\d\d)(?::(\d\d))?$/ )
148    {
149        ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
150    }
151    elsif ( $offset =~ /^([\+\-])?(\d\d)(\d\d)(\d\d)?$/ )
152    {
153        ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
154    }   
155    else
156    {       
157        return undef;
158    }
159       
160    $sign = '+' unless defined $sign;
161    return undef unless $hours >= 0 && $hours <= 99;
162    return undef unless $minutes >= 0 && $minutes <= 59;
163    return undef unless ! defined( $seconds ) || ( $seconds >= 0 && $seconds <= 59 );   
164       
165    my $total =  $hours * 3600 + $minutes * 60;
166    $total += $seconds if $seconds;
167    $total *= -1 if $sign eq '-';
168
169    return $total;
170}
171
1721;
173__END__
174
175=head1 NAME
176
177MT::DateTime
178
179=head1 AUTHOR & COPYRIGHT
180
181Please see L<MT/AUTHOR & COPYRIGHT>.
182
183=cut
Note: See TracBrowser for help on using the browser.