1#!/usr/bin/perl -w
2
3use strict;
4
5use Test::More tests => 537;
6
7use DateTime;
8
9
10my $t = DateTime->new( year => 1996, month => 11, day => 22,
11                       hour => 18, minute => 30, second => 20,
12                       time_zone => 'UTC',
13                     );
14$t->add( weeks => 8);
15
16is( $t->year, 1997, "year rollover");
17is( $t->month, 1, "month set on year rollover");
18is( $t->datetime, '1997-01-17T18:30:20', 'okay on year rollover' );
19
20$t->add( weeks => 2 );
21is( $t->datetime, '1997-01-31T18:30:20', 'Adding weeks' );
22
23$t->add( seconds => 15 );
24is( $t->datetime, '1997-01-31T18:30:35', 'Adding seconds' );
25
26$t->add( minutes => 12 );
27is( $t->datetime, '1997-01-31T18:42:35', 'Adding minutes' );
28
29$t->add( minutes => 25, hours => 3, seconds => 7 );
30is( $t->datetime, '1997-01-31T22:07:42', 'Adding h,m,s' );
31
32# Now, test the adding of durations
33$t = DateTime->new( year => 1986, month => 1, day => 28,
34                    hour => 16, minute => 38,
35                    time_zone => 'UTC' );
36
37$t->add( minutes => 1, seconds => 12 );
38is( $t->datetime, '1986-01-28T16:39:12', "Adding durations with minutes and seconds works");
39
40$t = DateTime->new( year => 1986, month => 1, day => 28,
41                    hour => 16, minute => 38,
42                    time_zone => 'UTC' );
43
44$t->add( seconds => 30 );
45is( $t->datetime, '1986-01-28T16:38:30', "Adding durations with seconds only works");
46
47$t = DateTime->new( year => 1986, month => 1, day => 28,
48                    hour => 16, minute => 38,
49                    time_zone => 'UTC' );
50
51$t->add( hours => 1, minutes => 10 );
52is( $t->datetime, '1986-01-28T17:48:00', "Adding durations with hours and minutes works");
53
54$t = DateTime->new( year => 1986, month => 1, day => 28,
55                    hour => 16, minute => 38,
56                    time_zone => 'UTC' );
57
58$t->add( days => 3 );
59is( $t->datetime, '1986-01-31T16:38:00', "Adding durations with days only works");
60
61
62$t = DateTime->new( year => 1986, month => 1, day => 28,
63                    hour => 16, minute => 38,
64                    time_zone => 'UTC' );
65
66$t->add( days => 3, hours => 2 );
67is( $t->datetime, '1986-01-31T18:38:00', "Adding durations with days and hours works");
68
69
70$t = DateTime->new( year => 1986, month => 1, day => 28,
71                    hour => 16, minute => 38,
72                    time_zone => 'UTC' );
73
74$t->add( days => 3, hours => 2, minutes => 20, seconds => 15 );
75is( $t->datetime, '1986-01-31T18:58:15', "Adding durations with days, hours, minutes, and seconds works");
76
77# Add 15M - this test failed at one point in N::I::Time
78$t = DateTime->new( year => 2001, month => 4, day => 5,
79                    hour => 16,
80                    time_zone => 'UTC' );
81
82$t->add( minutes => 15 );
83is( $t->datetime, '2001-04-05T16:15:00', "Adding minutes to an ical string");
84
85# Subtract a duration
86$t->add( minutes => -15 );
87is( $t->datetime, '2001-04-05T16:00:00', "Back where we started");
88
89undef $t;
90
91$t = DateTime->new( year => 1986, month => 1, day => 28,
92                    hour => 16, minute => 38,
93                    time_zone => 'UTC' );
94
95$t->add( seconds => 60 );
96is( $t->datetime, "1986-01-28T16:39:00", "adding positive seconds with seconds works" );
97$t->add( seconds => -120 );
98is( $t->datetime, "1986-01-28T16:37:00", "adding negative seconds with seconds works" );
99
100# test sub months
101$t = DateTime->new( year => 2001, month => 1, day => 31,
102                    time_zone => 'UTC',
103                  );
104$t->add(days => 1);
105is( $t->date, '2001-02-01', 'february 1st' );
106
107$t = DateTime->new( year => 2001, month => 2, day => 28,
108                    time_zone => 'UTC',
109                  );
110$t->add(days => 1);
111is( $t->date, '2001-03-01', 'march 1st' );
112
113$t = DateTime->new( year => 2001, month => 3, day => 31,
114                    time_zone => 'UTC',
115                  );
116$t->add(days => 1);
117is( $t->date, '2001-04-01', 'april 1st' );
118
119$t = DateTime->new( year => 2001, month => 4, day => 30,
120                    time_zone => 'UTC',
121                  );
122$t->add(days => 1);
123is( $t->date, '2001-05-01', 'may 1st' );
124
125$t = DateTime->new( year => 2001, month => 5, day => 31,
126                    time_zone => 'UTC',
127                  );
128$t->add(days => 1);
129is( $t->date, '2001-06-01', 'june 1st' );
130
131$t = DateTime->new( year => 2001, month => 6, day => 30,
132                    time_zone => 'UTC',
133                  );
134$t->add(days => 1);
135is( $t->date, '2001-07-01', 'july 1st' );
136
137$t = DateTime->new( year => 2001, month => 7, day => 31,
138                    time_zone => 'UTC',
139                  );
140$t->add(days => 1);
141is( $t->date, '2001-08-01', 'august 1st' );
142
143$t = DateTime->new( year => 2001, month => 8, day => 31,
144                    time_zone => 'UTC',
145                  );
146$t->add(days => 1);
147is( $t->date, '2001-09-01', 'september 1st' );
148
149$t = DateTime->new( year => 2001, month => 9, day => 30,
150                    time_zone => 'UTC',
151                  );
152$t->add(days => 1);
153is( $t->date, '2001-10-01', 'october 1st' );
154
155$t = DateTime->new( year => 2001, month => 10, day => 31,
156                    time_zone => 'UTC',
157                  );
158$t->add(days => 1);
159is( $t->date, '2001-11-01', 'november 1st' );
160
161$t = DateTime->new( year => 2001, month => 11, day => 30,
162                    time_zone => 'UTC',
163                  );
164$t->add(days => 1);
165is( $t->date, '2001-12-01', 'december 1st' );
166
167$t = DateTime->new( year => 2001, month => 12, day => 31,
168                    time_zone => 'UTC',
169                  );
170$t->add(days => 1);
171is( $t->date, '2002-01-01', 'january 1st' );
172
173# Adding years
174
175# Before leap day, not a leap year ...
176$t = DateTime->new( year => 2001, month => 2, day => 28,
177                    time_zone => 'UTC',
178                  );
179$t->add( years => 1 );
180is( $t->date, '2002-02-28', 'Adding a year' );
181$t->add( years => 17 );
182is( $t->date, '2019-02-28', 'Adding 17 years' );
183
184# After leap day, not a leap year ...
185$t = DateTime->new( year => 2001, month => 3, day => 28,
186                    time_zone => 'UTC',
187                  );
188$t->add( years => 1 );
189is( $t->date, '2002-03-28', 'Adding a year' );
190$t->add( years => 17 );
191is( $t->date, '2019-03-28', 'Adding 17 years' );
192
193# On leap day, in a leap year ...
194$t = DateTime->new( year => 2000, month => 2, day => 29,
195                    time_zone => 'UTC',
196                  );
197$t->add( years => 1 );
198is( $t->date, '2001-03-01', 'Adding a year' );
199$t->add( years => 17 );
200is( $t->date, '2018-03-01', 'Adding 17 years' );
201
202# Before leap day, in a leap year ...
203$t = DateTime->new( year => 2000, month => 2, day => 28,
204                    time_zone => 'UTC',
205                  );
206$t->add( years => 1 );
207is( $t->date, '2001-02-28', 'Adding a year' );
208$t->add( years => 17 );
209is( $t->date, '2018-02-28', 'Adding 17 years' );
210
211# After leap day, in a leap year ...
212$t = DateTime->new( year => 2000, month => 3, day => 28,
213                    time_zone => 'UTC',
214                  );
215$t->add( years => 1 );
216is( $t->date, '2001-03-28', 'Adding a year' );
217$t->add( years => 17 );
218is( $t->date, '2018-03-28', 'Adding 17 years' );
219
220# Test a bunch of years, before leap day
221for (1..99) {
222    $t = DateTime->new( year => 2000, month => 2, day => 28,
223                        time_zone => 'UTC',
224                      );
225    $t->add( years => $_ );
226    my $x = sprintf '%02d', $_;
227    is( $t->date, "20${x}-02-28", "Adding $_ years");
228}
229
230# Test a bunch of years, after leap day
231for (1..99) {
232    $t = DateTime->new( year => 2000, month => 3, day => 28,
233                        time_zone => 'UTC',
234                      );
235    $t->add( years => $_ );
236    my $x = sprintf '%02d', $_;
237    is( $t->date, "20${x}-03-28", "Adding $_ years");
238}
239
240# And more of the same, starting on a non-leap year
241
242# Test a bunch of years, before leap day
243for (1..97) {
244    $t = DateTime->new( year => 2002, month => 2, day => 28,
245                        time_zone => 'UTC',
246                      );
247    $t->add( years => $_ );
248    my $x = sprintf '%02d', $_ + 2;
249    is( $t->date, "20${x}-02-28", "Adding $_ years");
250}
251
252# Test a bunch of years, after leap day
253for (1..97) {
254    $t = DateTime->new( year => 2002, month => 3, day => 28,
255                        time_zone => 'UTC',
256                      );
257    $t->add( years => $_ );
258    my $x = sprintf '%02d', $_ + 2;
259    is( $t->date, "20${x}-03-28", "Adding $_ years");
260}
261
262# subtract years
263for (1..97) {
264    $t = DateTime->new( year => 1999, month => 3, day => 1,
265                        time_zone => 'UTC',
266                      );
267    $t->add( years => -$_ );
268    my $x = sprintf '%02d', 99 - $_;
269    is( $t->date, "19${x}-03-01", "Subtracting $_ years");
270}
271
272# test some old bugs
273
274# bug adding months where current month + months added were > 25
275$t = DateTime->new( year => 1997, month => 12, day => 1,
276                    time_zone => 'UTC',
277                  );
278$t->add( months => 14 );
279is( $t->date, '1999-02-01', 'Adding months--rollover year' );
280
281# bug subtracting months with year rollover
282$t = DateTime->new( year => 1997, month => 1, day => 1,
283                    time_zone => 'UTC',
284                  );
285$t->add( months => -1 );
286is( $t->date, '1996-12-01', 'Subtracting months--rollover year' );
287
288my $new = $t + DateTime::Duration->new( years => 2 );
289is( $new->date, '1998-12-01', 'test + overloading' );
290
291# test nanoseconds
292
293{
294    my $t = DateTime->new( year => 1997, month => 1, day => 1,
295                           hour => 1, minute => 1, second => 59,
296                           nanosecond => 500000000,
297                           time_zone => 'UTC',
298                         );
299
300    $t->add( nanoseconds => 500000000 );
301    is( $t->second, 0, 'fractional second rollover' );
302    $t->add( nanoseconds => 123000000 );
303    is( $t->fractional_second, 0.123, 'as fractional_second' );
304}
305
306{
307    my $dt = DateTime->new( year => 2003, month => 2, day => 28 );
308    $dt->add( months => 1, days => 1 );
309
310    is( $dt->ymd, '2003-04-01', 'order of units in date math' );
311}
312
313{
314    my $dt = DateTime->new( year => 2003, hour => 12, minute => 1);
315    $dt->add( minutes => 30, seconds => -1 );
316
317    is( $dt->hour,   12, 'hour is 12' );
318    is( $dt->minute, 30, 'minute is 30' );
319    is( $dt->second, 59, 'second is 59' );
320}
321