line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Date::Baha::i; |
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:GENE'; |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
# ABSTRACT: Convert to and from Baha'i dates |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.2001'; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
|
9
|
3
|
|
|
3
|
|
2423
|
use strict; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
89
|
|
10
|
3
|
|
|
3
|
|
16
|
use warnings; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
87
|
|
11
|
|
|
|
|
|
|
|
12
|
3
|
|
|
3
|
|
1186
|
use parent 'Exporter'; |
|
3
|
|
|
|
|
868
|
|
|
3
|
|
|
|
|
15
|
|
13
|
3
|
|
|
3
|
|
229
|
use vars qw(@EXPORT @EXPORT_OK); |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
195
|
|
14
|
|
|
|
|
|
|
@EXPORT = @EXPORT_OK = qw( |
15
|
|
|
|
|
|
|
as_string |
16
|
|
|
|
|
|
|
cycles |
17
|
|
|
|
|
|
|
days |
18
|
|
|
|
|
|
|
days_of_the_week |
19
|
|
|
|
|
|
|
from_bahai |
20
|
|
|
|
|
|
|
holy_days |
21
|
|
|
|
|
|
|
months |
22
|
|
|
|
|
|
|
next_holy_day |
23
|
|
|
|
|
|
|
to_bahai |
24
|
|
|
|
|
|
|
years |
25
|
|
|
|
|
|
|
); |
26
|
|
|
|
|
|
|
|
27
|
3
|
|
|
|
|
241
|
use Date::Calc qw( |
28
|
|
|
|
|
|
|
Add_Delta_Days |
29
|
|
|
|
|
|
|
Date_to_Days |
30
|
|
|
|
|
|
|
Day_of_Week |
31
|
|
|
|
|
|
|
leap_year |
32
|
3
|
|
|
3
|
|
841
|
); |
|
3
|
|
|
|
|
12139
|
|
33
|
3
|
|
|
3
|
|
1519
|
use Lingua::EN::Numbers qw(num2en_ordinal); |
|
3
|
|
|
|
|
6162
|
|
|
3
|
|
|
|
|
182
|
|
34
|
3
|
|
|
3
|
|
1517
|
use Lingua::EN::Numbers::Years; |
|
3
|
|
|
|
|
14850
|
|
|
3
|
|
|
|
|
232
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# Set constants |
37
|
3
|
|
|
3
|
|
25
|
use constant FACTOR => 19; # Groups of 19 |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
283
|
|
38
|
3
|
|
|
3
|
|
20
|
use constant FEBRUARY => 2; # Handy |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
130
|
|
39
|
3
|
|
|
3
|
|
17
|
use constant MARCH => 3; # Handy |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
136
|
|
40
|
3
|
|
|
3
|
|
18
|
use constant SHARAF => 16; # Handy |
|
3
|
|
|
|
|
26
|
|
|
3
|
|
|
|
|
168
|
|
41
|
3
|
|
|
3
|
|
18
|
use constant LAST_START_DAY => 2; # 1st day of fast |
|
3
|
|
|
|
|
12
|
|
|
3
|
|
|
|
|
148
|
|
42
|
3
|
|
|
3
|
|
61
|
use constant YEAR_START_DAY => 21; # Vernal equinox |
|
3
|
|
|
|
|
35
|
|
|
3
|
|
|
|
|
150
|
|
43
|
3
|
|
|
3
|
|
18
|
use constant LEAP_START_DAY => 26; # Intercalary days |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
177
|
|
44
|
3
|
|
|
3
|
|
20
|
use constant FIRST_YEAR => 1844; # History! |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
157
|
|
45
|
3
|
|
|
3
|
|
17
|
use constant ADJUST_YEAR => 1900; # Year factor |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
209
|
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
48
|
3
|
|
|
|
|
261
|
use constant CYCLE_YEAR => qw( |
49
|
|
|
|
|
|
|
Alif |
50
|
|
|
|
|
|
|
Ba |
51
|
|
|
|
|
|
|
Ab |
52
|
|
|
|
|
|
|
Dal |
53
|
|
|
|
|
|
|
Bab |
54
|
|
|
|
|
|
|
Vav |
55
|
|
|
|
|
|
|
Abad |
56
|
|
|
|
|
|
|
Jad |
57
|
|
|
|
|
|
|
Baha |
58
|
|
|
|
|
|
|
Hubb |
59
|
|
|
|
|
|
|
Bahhaj |
60
|
|
|
|
|
|
|
Javab |
61
|
|
|
|
|
|
|
Ahad |
62
|
|
|
|
|
|
|
Vahhab |
63
|
|
|
|
|
|
|
Vidad |
64
|
|
|
|
|
|
|
Badi |
65
|
|
|
|
|
|
|
Bahi |
66
|
|
|
|
|
|
|
Abha |
67
|
|
|
|
|
|
|
Vahid |
68
|
3
|
|
|
3
|
|
19
|
); |
|
3
|
|
|
|
|
6
|
|
69
|
3
|
|
|
|
|
528
|
use constant MONTH_DAY => qw( |
70
|
|
|
|
|
|
|
Baha |
71
|
|
|
|
|
|
|
Jalal |
72
|
|
|
|
|
|
|
Jamal |
73
|
|
|
|
|
|
|
'Azamat |
74
|
|
|
|
|
|
|
Nur |
75
|
|
|
|
|
|
|
Rahmat |
76
|
|
|
|
|
|
|
Kalimat |
77
|
|
|
|
|
|
|
Kamal |
78
|
|
|
|
|
|
|
Asma' |
79
|
|
|
|
|
|
|
'Izzat |
80
|
|
|
|
|
|
|
Mashiyyat |
81
|
|
|
|
|
|
|
'Ilm |
82
|
|
|
|
|
|
|
Qudrat |
83
|
|
|
|
|
|
|
Qawl |
84
|
|
|
|
|
|
|
Masa'il |
85
|
|
|
|
|
|
|
Sharaf |
86
|
|
|
|
|
|
|
Sultan |
87
|
|
|
|
|
|
|
Mulk |
88
|
|
|
|
|
|
|
'Ala |
89
|
|
|
|
|
|
|
Ayyam-i-Ha |
90
|
3
|
|
|
3
|
|
20
|
); |
|
3
|
|
|
|
|
5
|
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# We quote floats to avoid mis-computation. |
94
|
|
|
|
|
|
|
# Month => [Number, Start, End] # TODO ?, ? |
95
|
3
|
|
|
|
|
307
|
use constant MONTHS => { |
96
|
|
|
|
|
|
|
"Baha" => [ 0, '3.21', '4.08'], # 80, 98 |
97
|
|
|
|
|
|
|
"Jalal" => [ 1, '4.09', '4.27'], # 99, 117 |
98
|
|
|
|
|
|
|
"Jamal" => [ 2, '4.28', '5.16'], #118, 136 |
99
|
|
|
|
|
|
|
"'Azamat" => [ 3, '5.17', '6.04'], #137, 155 |
100
|
|
|
|
|
|
|
"Nur" => [ 4, '6.05', '6.23'], #156, 174 |
101
|
|
|
|
|
|
|
"Rahmat" => [ 5, '6.24', '7.12'], #175, 193 |
102
|
|
|
|
|
|
|
"Kalimat" => [ 6, '7.13', '7.31'], #194, 212 |
103
|
|
|
|
|
|
|
"Kamal" => [ 7, '8.01', '8.19'], #213, 231 |
104
|
|
|
|
|
|
|
"Asma'" => [ 8, '8.20', '9.07'], #232, 250 |
105
|
|
|
|
|
|
|
"'Izzat" => [ 9, '9.08', '9.26'], #251, 269 |
106
|
|
|
|
|
|
|
"Mashiyyat" => [10, '9.27', '10.15'], #270, 288 |
107
|
|
|
|
|
|
|
"'Ilm" => [11, '10.16', '11.03'], #289, 307 |
108
|
|
|
|
|
|
|
"Qudrat" => [12, '11.04', '11.22'], #308, 326 |
109
|
|
|
|
|
|
|
"Qawl" => [13, '11.23', '12.11'], #327, 345 |
110
|
|
|
|
|
|
|
"Masa'il" => [14, '12.12', '12.30'], #346, 364 |
111
|
|
|
|
|
|
|
"Sharaf" => [15, '12.31', '1.18'], #365, 18 |
112
|
|
|
|
|
|
|
"Sultan" => [16, '1.19', '2.06'], # 19, 37 |
113
|
|
|
|
|
|
|
"Mulk" => [17, '2.07', '2.25'], # 38, 56 |
114
|
|
|
|
|
|
|
"Ayyam-i-Ha" => [-1, '2.26', '3.01'], # 57, 60 |
115
|
|
|
|
|
|
|
"'Ala" => [18, '3.02', '3.20'], # 61, 79 |
116
|
3
|
|
|
3
|
|
21
|
}; |
|
3
|
|
|
|
|
5
|
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
|
119
|
3
|
|
|
|
|
331
|
use constant DOW_NAME => qw( |
120
|
|
|
|
|
|
|
Jalal |
121
|
|
|
|
|
|
|
Jamal |
122
|
|
|
|
|
|
|
Kaml |
123
|
|
|
|
|
|
|
Fidal |
124
|
|
|
|
|
|
|
'Idal |
125
|
|
|
|
|
|
|
Istijlal |
126
|
|
|
|
|
|
|
Istiqlal |
127
|
3
|
|
|
3
|
|
21
|
); |
|
3
|
|
|
|
|
5
|
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
|
130
|
3
|
|
|
|
|
6246
|
use constant HOLY_DAYS => { |
131
|
|
|
|
|
|
|
# Work suspended': |
132
|
|
|
|
|
|
|
"Naw Ruz" => [ '3.21' ], |
133
|
|
|
|
|
|
|
"First Day of Ridvan" => [ '4.21' ], |
134
|
|
|
|
|
|
|
"Ninth Day of Ridvan" => [ '4.29' ], |
135
|
|
|
|
|
|
|
"Twelfth Day of Ridvan" => [ '5.02' ], |
136
|
|
|
|
|
|
|
"Declaration of the Bab" => [ '5.23' ], |
137
|
|
|
|
|
|
|
"Ascension of Baha'u'llah" => [ '5.29' ], |
138
|
|
|
|
|
|
|
"Martyrdom of the Bab" => [ '7.09' ], |
139
|
|
|
|
|
|
|
"Birth of the Bab" => [ '10.20' ], |
140
|
|
|
|
|
|
|
"Birth of Baha'u'llah" => [ '11.12' ], |
141
|
|
|
|
|
|
|
# Work not suspended: |
142
|
|
|
|
|
|
|
"Ayyam-i-Ha" => [ '2.26', 4 ], # 5 days are calculated in leap years |
143
|
|
|
|
|
|
|
"The Fast" => [ '3.02', 19 ], |
144
|
|
|
|
|
|
|
"Days of Ridvan" => [ '4.21', 12 ], |
145
|
|
|
|
|
|
|
"Day of the Covenant" => [ '11.26' ], |
146
|
|
|
|
|
|
|
"Ascension of 'Abdu'l-Baha" => [ '11.28' ], |
147
|
3
|
|
|
3
|
|
20
|
}; |
|
3
|
|
|
|
|
14
|
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# List return functions |
150
|
0
|
|
|
0
|
1
|
0
|
sub cycles { return CYCLE_YEAR } |
151
|
0
|
|
|
0
|
1
|
0
|
sub years { return CYCLE_YEAR } |
152
|
0
|
|
|
0
|
1
|
0
|
sub months { return MONTH_DAY } |
153
|
0
|
|
|
0
|
1
|
0
|
sub days { return (MONTH_DAY)[0 .. 18] } |
154
|
0
|
|
|
0
|
1
|
0
|
sub days_of_the_week { return DOW_NAME } |
155
|
0
|
|
|
0
|
1
|
0
|
sub holy_days { return HOLY_DAYS } |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
sub to_bahai { |
158
|
2
|
|
|
2
|
1
|
1351
|
my %args = @_; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# Grab the ymd from the arguments if they have been passed in. |
161
|
2
|
|
|
|
|
8
|
my ($year, $month, $day) = @args{qw(year month day)}; |
162
|
|
|
|
|
|
|
# Make sure we have a proper ymd before proceeding. |
163
|
2
|
|
|
|
|
9
|
($year, $month, $day) = _ymd( |
164
|
|
|
|
|
|
|
%args, |
165
|
|
|
|
|
|
|
year => $year, |
166
|
|
|
|
|
|
|
month => $month, |
167
|
|
|
|
|
|
|
day => $day, |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
|
170
|
2
|
|
|
|
|
4
|
my ($bahai_month, $bahai_day); |
171
|
|
|
|
|
|
|
|
172
|
2
|
|
|
|
|
3
|
for (values %{ MONTHS() }) { |
|
2
|
|
|
|
|
8
|
|
173
|
39
|
|
|
|
|
81
|
my ($days, $lower, $upper) = _setup_date_comparison( |
174
|
|
|
|
|
|
|
$year, $month, $day, @$_[1,2] |
175
|
|
|
|
|
|
|
); |
176
|
|
|
|
|
|
|
|
177
|
39
|
100
|
100
|
|
|
116
|
if ($days >= $lower && $days <= $upper) { |
178
|
2
|
|
|
|
|
4
|
$bahai_month = $_->[0]; |
179
|
2
|
|
|
|
|
4
|
$bahai_day = $days - $lower; |
180
|
2
|
|
|
|
|
5
|
last; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# Build the date hash to return. |
185
|
2
|
|
|
|
|
8
|
return _build_date( |
186
|
|
|
|
|
|
|
$year, $month, $day, $bahai_month, $bahai_day, |
187
|
|
|
|
|
|
|
%args |
188
|
|
|
|
|
|
|
); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub from_bahai { |
192
|
366
|
|
|
366
|
1
|
197064
|
my %args = @_; |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Figure out the year. |
195
|
366
|
|
|
|
|
769
|
my $year = $args{year} + FIRST_YEAR; |
196
|
366
|
100
|
100
|
|
|
1517
|
$year-- unless $args{month} > SHARAF || $args{month} == -1; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Reset the month number if we are given Ayyam-i-Ha. |
199
|
366
|
100
|
|
|
|
865
|
$args{month} = 0 if $args{month} == -1; |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
# This ugliness actually finds the month and day number. |
202
|
366
|
|
|
|
|
1061
|
my $day = (MONTHS->{ (MONTH_DAY)[$args{month} - 1] })->[1]; |
203
|
366
|
|
|
|
|
1252
|
(my $month, $day) = split /\./, $day; |
204
|
|
|
|
|
|
|
($year, $month, $day) = Add_Delta_Days( |
205
|
366
|
|
|
|
|
1306
|
$year, $month, $day, $args{day} - 1 |
206
|
|
|
|
|
|
|
); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
return wantarray |
209
|
366
|
50
|
|
|
|
1421
|
? ($year, $month, $day) |
210
|
|
|
|
|
|
|
: join '/', $year, $month, $day; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub as_string { |
214
|
|
|
|
|
|
|
# XXX With Lingua::EN::Numbers, naively assume that we only care about English. |
215
|
8
|
|
|
8
|
1
|
5918
|
my ($date_hash, %args) = @_; |
216
|
|
|
|
|
|
|
|
217
|
8
|
50
|
|
|
|
25
|
$args{size} = 1 unless defined $args{size}; |
218
|
8
|
50
|
|
|
|
25
|
$args{numeric} = 0 unless defined $args{numeric}; |
219
|
8
|
50
|
|
|
|
15
|
$args{alpha} = 1 unless defined $args{alpha}; |
220
|
|
|
|
|
|
|
|
221
|
8
|
|
|
|
|
12
|
my $date; |
222
|
|
|
|
|
|
|
|
223
|
8
|
50
|
|
|
|
22
|
my $is_ayyam_i_ha = $date_hash->{month} == -1 ? 1 : 0; |
224
|
|
|
|
|
|
|
|
225
|
8
|
100
|
100
|
|
|
85
|
if (!$args{size} && $args{numeric} && $args{alpha}) { |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
226
|
|
|
|
|
|
|
# short alpha-numeric |
227
|
|
|
|
|
|
|
$date .= sprintf '%s (%d), %s (%d) of %s (%d), year %d, %s (%d) of %s (%d)', |
228
|
1
|
|
|
|
|
10
|
@$date_hash{qw( |
229
|
|
|
|
|
|
|
dow_name dow day_name day month_name month |
230
|
|
|
|
|
|
|
year year_name cycle_year cycle_name cycle |
231
|
|
|
|
|
|
|
)}; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
elsif ($args{size} && $args{numeric} && $args{alpha}) { |
234
|
|
|
|
|
|
|
# long alpha-numeric |
235
|
|
|
|
|
|
|
# XXX Fugly hacking begins. |
236
|
1
|
50
|
|
|
|
5
|
my $month_string = $is_ayyam_i_ha ? '%s%s' : 'the %s month %s'; |
237
|
1
|
|
|
|
|
5
|
my $n = year2en($date_hash->{year}); |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
$date .= sprintf |
240
|
|
|
|
|
|
|
"%s week day %s, %s day %s of $month_string, year %s (%d), %s year %s of the %s vahid %s of the %s kull-i-shay", |
241
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{dow}), |
242
|
|
|
|
|
|
|
$date_hash->{dow_name}, |
243
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{day}), |
244
|
|
|
|
|
|
|
$date_hash->{day_name}, |
245
|
|
|
|
|
|
|
($is_ayyam_i_ha ? '' : num2en_ordinal($date_hash->{month})), |
246
|
|
|
|
|
|
|
$date_hash->{month_name}, |
247
|
|
|
|
|
|
|
$n, |
248
|
|
|
|
|
|
|
$date_hash->{year}, |
249
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{cycle_year}), |
250
|
|
|
|
|
|
|
$date_hash->{year_name}, |
251
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{cycle}), |
252
|
|
|
|
|
|
|
$date_hash->{cycle_name}, |
253
|
1
|
50
|
|
|
|
149
|
num2en_ordinal($date_hash->{kull_i_shay}); |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
elsif (!$args{size} && $args{numeric} && !$args{alpha}) { |
256
|
|
|
|
|
|
|
# short numeric |
257
|
1
|
|
|
|
|
5
|
$date .= sprintf '%s/%s/%s', @$date_hash{qw(month day year)}; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
elsif ($args{size} && $args{numeric}) { |
260
|
|
|
|
|
|
|
# long numeric |
261
|
|
|
|
|
|
|
$date .= sprintf |
262
|
|
|
|
|
|
|
'%s day of the week, %s day of the %s month, year %s, %s year of the %s vahid of the %s kull-i-shay', |
263
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{dow}), |
264
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{day}), |
265
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{month}), |
266
|
|
|
|
|
|
|
$date_hash->{year}, |
267
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{cycle_year}), |
268
|
|
|
|
|
|
|
num2en_ordinal($date_hash->{cycle}), |
269
|
1
|
|
|
|
|
4
|
num2en_ordinal($date_hash->{kull_i_shay}); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
elsif (!$args{size} && $args{alpha}) { |
272
|
|
|
|
|
|
|
# short alpha |
273
|
|
|
|
|
|
|
$date .= sprintf '%s, %s of %s, %s of %s', |
274
|
1
|
|
|
|
|
9
|
@$date_hash{qw( |
275
|
|
|
|
|
|
|
dow_name day_name month_name year_name cycle_name |
276
|
|
|
|
|
|
|
)}; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
else { |
279
|
|
|
|
|
|
|
# long alpha |
280
|
3
|
50
|
|
|
|
7
|
my $month_string = $is_ayyam_i_ha ? '%s' : 'month %s'; |
281
|
3
|
|
|
|
|
10
|
my $n = year2en($date_hash->{year}); |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
$date .= sprintf |
284
|
|
|
|
|
|
|
"week day %s, day %s of $month_string, year %s, %s of the vahid %s of the %s kull-i-shay", |
285
|
|
|
|
|
|
|
@$date_hash{qw(dow_name day_name month_name)}, |
286
|
|
|
|
|
|
|
$n, |
287
|
|
|
|
|
|
|
@$date_hash{qw(year_name cycle_name)}, |
288
|
3
|
|
|
|
|
217
|
num2en_ordinal($date_hash->{kull_i_shay}); |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
8
|
0
|
33
|
|
|
426
|
if ($date_hash->{holy_day} && $args{size}) { |
292
|
0
|
|
|
|
|
0
|
$date .= ', holy day: ' . join '', keys %{ $date_hash->{holy_day} }; |
|
0
|
|
|
|
|
0
|
|
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
8
|
|
|
|
|
28
|
return $date; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
sub next_holy_day { |
299
|
0
|
|
|
0
|
1
|
0
|
my ($year, $month, $day) = @_; |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Use today if we are not provided with a date. |
302
|
0
|
|
|
|
|
0
|
($year, $month, $day) = _ymd( |
303
|
|
|
|
|
|
|
year => $year, |
304
|
|
|
|
|
|
|
month => $month, |
305
|
|
|
|
|
|
|
day => $day, |
306
|
|
|
|
|
|
|
); |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# Construct our lists of pseudo real number dates. |
309
|
0
|
|
|
|
|
0
|
my %inverted = _invert_holy_days($year); |
310
|
0
|
|
|
|
|
0
|
my @sorted = sort { $a <=> $b } keys %inverted; |
|
0
|
|
|
|
|
0
|
|
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
# Make the month and day a pseudo real number. |
313
|
0
|
|
|
|
|
0
|
my $m_d = "$month.$day"; |
314
|
0
|
|
|
|
|
0
|
my $holy_date; |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# Find the first date greater than the one provided. |
317
|
0
|
|
|
|
|
0
|
for (@sorted) { |
318
|
0
|
0
|
|
|
|
0
|
if ($m_d < $_) { |
319
|
0
|
|
|
|
|
0
|
$holy_date = $_; |
320
|
0
|
|
|
|
|
0
|
last; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# If one was not found, grab the last date in the list. |
325
|
0
|
0
|
|
|
|
0
|
$holy_date = $sorted[-1] unless $holy_date; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# Make this look like a date again. |
328
|
0
|
|
|
|
|
0
|
(my $date = $holy_date) =~ s/\./\//; |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
return wantarray |
331
|
0
|
0
|
|
|
|
0
|
? ($inverted{$holy_date}, $date) |
332
|
|
|
|
|
|
|
: "$inverted{$holy_date} $date"; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Helper functions |
336
|
|
|
|
|
|
|
# Date comparison gymnastics. |
337
|
|
|
|
|
|
|
sub _setup_date_comparison { |
338
|
39
|
|
|
39
|
|
61
|
my ($y, $m, $d, $s, $e) = @_; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# Dates are encoded as decimals. |
341
|
39
|
|
|
|
|
88
|
my ($start_month, $start_day) = split /\./, $s; |
342
|
39
|
|
|
|
|
91
|
my ($end_month, $end_day) = split /\./, $e; |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# Slide either the start or end year, given the month we're |
345
|
|
|
|
|
|
|
# looking at. |
346
|
39
|
|
|
|
|
68
|
my ($start_year, $end_year) = ($y, $y); |
347
|
39
|
100
|
|
|
|
79
|
if ($end_month < $start_month) { |
348
|
2
|
50
|
|
|
|
12
|
if ($m == $start_month) { |
|
|
50
|
|
|
|
|
|
349
|
0
|
|
|
|
|
0
|
$end_year++; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
elsif ($m == $end_month) { |
352
|
0
|
|
|
|
|
0
|
$start_year--; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
return |
357
|
39
|
|
|
|
|
148
|
Date_to_Days($y, $m, $d), |
358
|
|
|
|
|
|
|
Date_to_Days($start_year, $start_month, $start_day), |
359
|
|
|
|
|
|
|
Date_to_Days($end_year, $end_month, $end_day); |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
sub _build_date { |
363
|
2
|
|
|
2
|
|
7
|
my ($year, $month, $day, $new_month, $new_day, %args) = @_; |
364
|
|
|
|
|
|
|
|
365
|
2
|
|
|
|
|
3
|
my %date; |
366
|
2
|
|
|
|
|
6
|
@date{qw(month day)} = ($new_month, $new_day); |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
# Set the day of the week (rotated by 2). |
369
|
2
|
|
|
|
|
9
|
$date{dow} = Day_of_Week($year, $month, $day); |
370
|
2
|
|
|
|
|
4
|
$date{dow} += 2; |
371
|
2
|
50
|
|
|
|
15
|
$date{dow} = $date{dow} - 7 if $date{dow} > 7; |
372
|
2
|
|
|
|
|
7
|
$date{dow_name} = (DOW_NAME)[$date{dow} - 1]; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# Set the day. |
375
|
2
|
|
|
|
|
5
|
$date{day_name} = (MONTH_DAY)[$date{day}]; |
376
|
2
|
|
|
|
|
4
|
$date{day}++; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# Set the the month. |
379
|
2
|
|
|
|
|
3
|
$date{month_name} = (MONTH_DAY)[$date{month}]; |
380
|
|
|
|
|
|
|
# Fix the month number, unless we are in Ayyam-i-Ha. |
381
|
2
|
50
|
|
|
|
12
|
$date{month}++ unless $date{month} == -1; |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
# Set the year. |
384
|
|
|
|
|
|
|
# Algorithm lifted from Danesh's "bahaidate". |
385
|
2
|
50
|
33
|
|
|
23
|
$date{year} = ($month < MARCH) || |
386
|
|
|
|
|
|
|
($month == MARCH && $day < YEAR_START_DAY) |
387
|
|
|
|
|
|
|
? $year - FIRST_YEAR |
388
|
|
|
|
|
|
|
: $year - (FIRST_YEAR - 1); |
389
|
|
|
|
|
|
|
|
390
|
2
|
|
|
|
|
16
|
$date{year_name} = (CYCLE_YEAR)[($date{year} - 1) % FACTOR]; |
391
|
2
|
|
|
|
|
5
|
$date{cycle_year} = $date{year} % FACTOR; |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# Set the cycle. |
394
|
2
|
|
|
|
|
9
|
$date{cycle} = int($date{year} / FACTOR) + 1; |
395
|
2
|
|
|
|
|
4
|
$date{cycle_name} = (CYCLE_YEAR)[($date{cycle} - 1) % FACTOR]; |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# Set the Kull-i-Shay. |
398
|
2
|
|
|
|
|
5
|
$date{kull_i_shay} = int($date{cycle} / FACTOR) + 1; |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
# $date{timezone} = tz_local_offset(); |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
# Get the holy day. |
403
|
2
|
|
|
|
|
6
|
my %inverted = _invert_holy_days($year); |
404
|
2
|
|
|
|
|
12
|
my $m_d = sprintf '%d.%d', $month, $day; |
405
|
2
|
50
|
|
|
|
7
|
$date{holy_day} = $inverted{$m_d} if exists $inverted{$m_d}; |
406
|
|
|
|
|
|
|
|
407
|
2
|
50
|
|
|
|
33
|
return wantarray ? %date : as_string(\%date, %args); |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub _invert_holy_days { |
411
|
2
|
|
33
|
2
|
|
6
|
my $year = shift || (localtime)[5] + ADJUST_YEAR; |
412
|
|
|
|
|
|
|
|
413
|
2
|
|
|
|
|
4
|
my %inverted; |
414
|
|
|
|
|
|
|
|
415
|
2
|
|
|
|
|
3
|
while (my ($name, $date) = each %{ HOLY_DAYS() }) { |
|
30
|
|
|
|
|
74
|
|
416
|
28
|
|
|
|
|
68
|
$inverted{$date->[0]} = $name; |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# Does this date contain a day span? |
419
|
28
|
100
|
|
|
|
59
|
if (@$date > 1) { |
420
|
|
|
|
|
|
|
# Increment the Ayyam-i-Ha day if we are in a leap year. |
421
|
6
|
50
|
66
|
|
|
22
|
$date->[1]++ if $name eq 'Ayyam-i-Ha' && leap_year($year); |
422
|
|
|
|
|
|
|
|
423
|
6
|
|
|
|
|
16
|
for (1 .. $date->[1] - 1) { |
424
|
64
|
|
|
|
|
197
|
(undef, my $month, my $day) = Add_Delta_Days( |
425
|
|
|
|
|
|
|
$year, split(/\./, $date->[0]), $_ |
426
|
|
|
|
|
|
|
); |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
# Pre-pad the day number with a zero. |
429
|
64
|
|
|
|
|
240
|
$inverted{ sprintf '%d.%d', $month, $day } = $name; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
2
|
|
|
|
|
54
|
return %inverted; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
# Return a ymd date array but try to honor the epoch and use_gmtime settings. |
438
|
|
|
|
|
|
|
sub _ymd { |
439
|
2
|
|
|
2
|
|
6
|
my %args = @_; |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# Use the system time, if a ymd is not provided. |
442
|
2
|
50
|
33
|
|
|
22
|
unless($args{year} && $args{month} && $args{day}) { |
|
|
|
33
|
|
|
|
|
443
|
0
|
|
0
|
|
|
0
|
$args{epoch} ||= time; |
444
|
|
|
|
|
|
|
($args{year}, $args{month}, $args{day}) = $args{use_gmtime} |
445
|
|
|
|
|
|
|
? (gmtime $args{epoch})[5,4,3] |
446
|
0
|
0
|
|
|
|
0
|
: (localtime $args{epoch})[5,4,3]; |
447
|
|
|
|
|
|
|
# Fix the year and the month. |
448
|
0
|
|
|
|
|
0
|
$args{year} += ADJUST_YEAR; |
449
|
0
|
|
|
|
|
0
|
$args{month}++; |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
2
|
|
|
|
|
7
|
return $args{year}, $args{month}, $args{day}; |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
1; |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
__END__ |