line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#
|
2
|
|
|
|
|
|
|
# WeekOfYear.pm
|
3
|
|
|
|
|
|
|
#
|
4
|
|
|
|
|
|
|
# Synopsis: see POD at end of file
|
5
|
|
|
|
|
|
|
#
|
6
|
|
|
|
|
|
|
package Date::WeekOfYear;
|
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
37576
|
use strict;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
39
|
|
9
|
1
|
|
|
1
|
|
5
|
use warnings;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
30
|
|
10
|
1
|
|
|
1
|
|
975
|
use Time::Local;
|
|
1
|
|
|
|
|
1628
|
|
|
1
|
|
|
|
|
61
|
|
11
|
1
|
|
|
1
|
|
680
|
use parent 'Exporter';
|
|
1
|
|
|
|
|
273
|
|
|
1
|
|
|
|
|
4
|
|
12
|
1
|
|
|
1
|
|
832
|
use integer; # Integer math, so we don't need floor
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
5
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = '1.06';
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our @ISA = qw(Exporter);
|
17
|
|
|
|
|
|
|
our %EXPORT_TAGS = (
|
18
|
|
|
|
|
|
|
'mode' => [ qw( WeekOfYear WOY_OLD_MODE WOY_ISO_MODE ) ],
|
19
|
|
|
|
|
|
|
'all' => [ qw( WeekOfYear WOY_OLD_MODE WOY_ISO_MODE is_leap_year day_of_year jan1week_day WeekOfYear week_day week_number ) ],
|
20
|
|
|
|
|
|
|
);
|
21
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
22
|
|
|
|
|
|
|
our @EXPORT = qw( WeekOfYear );
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Weekday constants
|
25
|
|
|
|
|
|
|
use constant {
|
26
|
1
|
|
|
|
|
784
|
SUNDAY => 0,
|
27
|
|
|
|
|
|
|
MONDAY => 1,
|
28
|
|
|
|
|
|
|
TUESDAY => 2,
|
29
|
|
|
|
|
|
|
WEDNESDAY => 3,
|
30
|
|
|
|
|
|
|
THURSDAY => 4,
|
31
|
|
|
|
|
|
|
FRIDAY => 5,
|
32
|
|
|
|
|
|
|
SATURDAY => 6,
|
33
|
1
|
|
|
1
|
|
103
|
};
|
|
1
|
|
|
|
|
1
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Pseudo constants
|
36
|
192
|
|
|
192
|
1
|
1560
|
sub WOY_OLD_MODE { 1 }
|
37
|
365
|
|
|
365
|
1
|
1166
|
sub WOY_ISO_MODE { 2 }
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub is_leap_year
|
41
|
|
|
|
|
|
|
{ |
42
|
|
|
|
|
|
|
|
43
|
464
|
|
|
464
|
1
|
441
|
my $year = shift; # eg 2014
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# See POD for details of the algorithm.
|
46
|
464
|
100
|
100
|
|
|
2246
|
my $is_ly = ((($year % 4 == 0) && ($year % 100 != 0)) || ($year % 400 == 0)) ? 1 : 0;
|
47
|
|
|
|
|
|
|
#print STDERR "is_ly=$is_ly $year\n";
|
48
|
|
|
|
|
|
|
|
49
|
464
|
|
|
|
|
834
|
return $is_ly;
|
50
|
|
|
|
|
|
|
}
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub day_of_year
|
53
|
|
|
|
|
|
|
{
|
54
|
|
|
|
|
|
|
# Return the day of the year, 1 being the first day (unlike localtime()) based on day of month and month
|
55
|
356
|
|
|
356
|
1
|
381
|
my ($year, $month, $day) = @_; # year is YYYY (eg 2014), month is 1-12, Jan=1, day is day of month
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Days to mth start Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
|
58
|
356
|
|
|
|
|
812
|
my @days_in_month = (undef, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
|
59
|
|
|
|
|
|
|
|
60
|
356
|
|
|
|
|
428
|
my $doy = $day + $days_in_month[$month];
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Need to adjust for leap year if after Feb
|
63
|
356
|
100
|
100
|
|
|
1013
|
$doy++ if ($month > 2 && is_leap_year($year));
|
64
|
|
|
|
|
|
|
|
65
|
356
|
|
|
|
|
661
|
return $doy;
|
66
|
|
|
|
|
|
|
}
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub jan1week_day
|
69
|
|
|
|
|
|
|
{
|
70
|
363
|
|
|
363
|
1
|
387
|
my ($year) = @_; # year is YYYY (eg 2014)
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Here weekday 1=Mon, 2=Tue, 7=Sun (not 0 as localtime())
|
73
|
363
|
|
|
|
|
423
|
my $yy = ($year - 1) % 100;
|
74
|
363
|
|
|
|
|
615
|
my $jan1wd = 1 + (((($year -1 - $yy) / 100 ) % 4) * 5 + $yy + $yy/4) % 7;
|
75
|
|
|
|
|
|
|
|
76
|
363
|
|
|
|
|
528
|
return $jan1wd;
|
77
|
|
|
|
|
|
|
}
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub week_day
|
80
|
|
|
|
|
|
|
{
|
81
|
|
|
|
|
|
|
# Here weekday 1=Mon, 2=Tue, 3=Wed, 4=Thu,...7=Sun (not 0 as localtime())
|
82
|
178
|
|
|
178
|
1
|
212
|
my ($year, $month, $day) = @_; # year is YYYY (eg 2014), month is 1-12, Jan=1, day is day of month
|
83
|
|
|
|
|
|
|
|
84
|
178
|
|
|
|
|
265
|
my $doy = day_of_year($year, $month, $day);
|
85
|
178
|
|
|
|
|
247
|
my $jan1wd = jan1week_day($year, $month, $day);
|
86
|
|
|
|
|
|
|
|
87
|
178
|
|
|
|
|
228
|
my $wd = 1 + (($doy + $jan1wd - 2) % 7);
|
88
|
|
|
|
|
|
|
|
89
|
178
|
|
|
|
|
234
|
return $wd;
|
90
|
|
|
|
|
|
|
}
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub week_number
|
93
|
|
|
|
|
|
|
{
|
94
|
178
|
|
|
178
|
1
|
223
|
my ($year, $month, $day) = @_; # year is YYYY (eg 2014), month is 1-12, Jan=1, day is day of month
|
95
|
|
|
|
|
|
|
|
96
|
178
|
|
|
|
|
190
|
my $year_number = $year;
|
97
|
178
|
|
|
|
|
736
|
my $week_number;
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
|
100
|
178
|
|
|
|
|
326
|
my $is_leap_y = is_leap_year($year);
|
101
|
178
|
|
|
|
|
303
|
my $is_leap_prev_y = is_leap_year($year - 1);
|
102
|
178
|
|
|
|
|
306
|
my $doy = day_of_year($year, $month, $day);
|
103
|
178
|
|
|
|
|
269
|
my $jan1wd = jan1week_day($year, $month, $day);
|
104
|
178
|
|
|
|
|
457
|
my $wd = week_day($year, $month, $day);
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
#print STDERR "year=$year, month=$month, day=$day, is_leap_y=$is_leap_y, is_leap_prev_y=$is_leap_prev_y, doy=$doy, jan1wd=$jan1wd, wd=$wd\n";
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# Does YYYYMMDD fall in year YYYY-1, weeknumber 52 or 53
|
109
|
178
|
100
|
100
|
|
|
484
|
if ($doy <= (8 - $jan1wd) && $jan1wd > 4)
|
110
|
|
|
|
|
|
|
{
|
111
|
46
|
|
|
|
|
47
|
$year_number--;
|
112
|
46
|
100
|
100
|
|
|
204
|
if ($jan1wd == 5 || ($jan1wd == 6 && $is_leap_prev_y))
|
|
|
|
66
|
|
|
|
|
113
|
|
|
|
|
|
|
{
|
114
|
10
|
|
|
|
|
14
|
$week_number = 53;
|
115
|
|
|
|
|
|
|
}
|
116
|
|
|
|
|
|
|
else
|
117
|
|
|
|
|
|
|
{
|
118
|
36
|
|
|
|
|
48
|
$week_number = 52;
|
119
|
|
|
|
|
|
|
}
|
120
|
|
|
|
|
|
|
}
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# Does YYYYMMDD fall in YYYY+1, weeknumber 1
|
123
|
178
|
100
|
|
|
|
321
|
if ($year_number == $year)
|
124
|
|
|
|
|
|
|
{
|
125
|
132
|
100
|
|
|
|
206
|
my $days_in_year = $is_leap_y ? 366 : 365;
|
126
|
|
|
|
|
|
|
|
127
|
132
|
100
|
|
|
|
262
|
if (($days_in_year - $doy) < (4 - $wd))
|
128
|
|
|
|
|
|
|
{
|
129
|
8
|
|
|
|
|
7
|
$year_number++;
|
130
|
8
|
|
|
|
|
12
|
$week_number = 1;
|
131
|
|
|
|
|
|
|
}
|
132
|
|
|
|
|
|
|
}
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# Does YYYYMMDD fall in YYYY weeknumber 1 -> 53
|
135
|
178
|
100
|
|
|
|
301
|
if ($year_number == $year)
|
136
|
|
|
|
|
|
|
{
|
137
|
124
|
|
|
|
|
178
|
$week_number = ($doy + 6 - $wd + $jan1wd)/7;
|
138
|
124
|
100
|
|
|
|
221
|
$week_number-- if ($jan1wd > 4);
|
139
|
|
|
|
|
|
|
}
|
140
|
|
|
|
|
|
|
|
141
|
178
|
|
|
|
|
316
|
return ($week_number, $year_number);
|
142
|
|
|
|
|
|
|
}
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub WeekOfYear
|
145
|
|
|
|
|
|
|
{
|
146
|
185
|
|
|
185
|
1
|
161754
|
my ($time, $mode) = @_;
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Make sure we have a mode
|
149
|
185
|
100
|
|
|
|
464
|
$mode = 0 unless defined $mode;
|
150
|
|
|
|
|
|
|
|
151
|
185
|
|
|
|
|
195
|
my ($tm_day, $tm_mth, $tm_year, $wkday, $yrday);
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# Post version 1.4 can be passed a hash ref for the time
|
154
|
|
|
|
|
|
|
# The hash ref must have a year, month and day
|
155
|
|
|
|
|
|
|
# This allows working past or before dates that can be handled by localtime
|
156
|
185
|
100
|
100
|
|
|
768
|
if (($mode == 0 || $mode == WOY_ISO_MODE) && ref($time) eq 'HASH')
|
|
|
|
100
|
|
|
|
|
157
|
|
|
|
|
|
|
{
|
158
|
2
|
|
|
|
|
5
|
$tm_day = $time->{day};
|
159
|
2
|
|
|
|
|
4
|
$tm_mth = $time->{month} - 1;
|
160
|
2
|
|
|
|
|
3
|
$tm_year = $time->{year} - 1900;
|
161
|
|
|
|
|
|
|
}
|
162
|
|
|
|
|
|
|
else
|
163
|
|
|
|
|
|
|
{
|
164
|
|
|
|
|
|
|
# Set to the current time if nothing provided
|
165
|
183
|
50
|
33
|
|
|
1159
|
$time = time unless (defined($time) && $time =~ /^\s*\d+\s*$/);
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# wkday is the day of the week, 0=Sunday, 1=Monday.. 4=Thursday
|
168
|
183
|
|
|
|
|
4427
|
($tm_day, $tm_mth, $tm_year, $wkday, $yrday) = (localtime($time))[3..7];
|
169
|
|
|
|
|
|
|
}
|
170
|
|
|
|
|
|
|
|
171
|
185
|
|
|
|
|
288
|
my $wkNo;
|
172
|
|
|
|
|
|
|
|
173
|
185
|
100
|
|
|
|
339
|
if ($mode == WOY_OLD_MODE)
|
174
|
|
|
|
|
|
|
{
|
175
|
|
|
|
|
|
|
# Pre version 1.4 functionality
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# What is the week day for 1 Jan of the year in question
|
178
|
7
|
|
|
|
|
19
|
my ($soywkday) = jan1week_day($tm_year + 1900);
|
179
|
|
|
|
|
|
|
|
180
|
7
|
100
|
|
|
|
18
|
$wkNo = int($yrday / 7) + 1 + (($wkday < $soywkday)? 1:0);
|
181
|
|
|
|
|
|
|
|
182
|
7
|
50
|
|
|
|
49
|
return wantarray ? ($wkNo, $tm_year + 1900) : $wkNo;
|
183
|
|
|
|
|
|
|
}
|
184
|
|
|
|
|
|
|
else
|
185
|
|
|
|
|
|
|
{
|
186
|
178
|
|
|
|
|
441
|
my ($w, $y) = week_number($tm_year + 1900, $tm_mth + 1, $tm_day);
|
187
|
|
|
|
|
|
|
|
188
|
178
|
100
|
|
|
|
317
|
if ($mode == WOY_ISO_MODE)
|
189
|
|
|
|
|
|
|
{
|
190
|
|
|
|
|
|
|
# YYYY-WXX where YYYY is the year, W denotes the week, and XX is the week number, eg 1970-W53
|
191
|
90
|
|
|
|
|
475
|
return sprintf('%d-W%02d', $y, $w);
|
192
|
|
|
|
|
|
|
}
|
193
|
|
|
|
|
|
|
else
|
194
|
|
|
|
|
|
|
{
|
195
|
|
|
|
|
|
|
# The new default output
|
196
|
88
|
50
|
|
|
|
316
|
return wantarray ? ($w, $y) : $w;
|
197
|
|
|
|
|
|
|
}
|
198
|
|
|
|
|
|
|
}
|
199
|
|
|
|
|
|
|
}
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
1;
|
203
|
|
|
|
|
|
|
__END__
|