2 use Test::MockTime qw(set_fixed_time restore_time);
7 use RT::Test tests => 175;
13 my $date = RT::Date->new(RT->SystemUser);
14 isa_ok($date, 'RT::Date', "constructor returned RT::Date oject");
15 $date = $date->new(RT->SystemUser);
16 isa_ok($date, 'RT::Date', "constructor returned RT::Date oject");
20 # set timezone in all places to UTC
21 RT->SystemUser->UserObj->__Set(Field => 'Timezone', Value => 'UTC')
22 if RT->SystemUser->UserObj->Timezone;
23 RT->Config->Set( Timezone => 'UTC' );
28 my $user = RT::User->new(RT->SystemUser);
29 my($uid, $msg) = $user->Create(
30 Name => "date_api". rand(200),
34 ok($uid, "user was created") or diag("error: $msg");
35 $current_user = RT::CurrentUser->new($user);
39 my $date = RT::Date->new( $current_user );
40 is($date->Timezone('user'), 'UTC', "dropped all timzones to UTC");
41 is($date->Timezone('server'), 'UTC', "dropped all timzones to UTC");
42 is($date->Timezone('unknown'), 'UTC', "with wrong context returns UTC");
44 $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
45 is($current_user->UserObj->Timezone,
47 "successfuly changed user's timezone");
48 is($date->Timezone('user'),
50 "in user context returns user's timezone");
51 is($date->Timezone('server'), 'UTC', "wasn't changed");
53 RT->Config->Set( Timezone => 'Africa/Ouagadougou' );
54 is($date->Timezone('server'),
56 "timezone of the RT server was changed");
57 is($date->Timezone('user'),
59 "in user context still returns user's timezone");
61 $current_user->UserObj->__Set( Field => 'Timezone', Value => '');
62 is_empty($current_user->UserObj->Timezone,
63 "successfuly changed user's timezone");
64 is($date->Timezone('user'),
66 "in user context returns timezone of the server if user's one is not defined");
68 RT->Config->Set( Timezone => 'GMT' );
69 is($date->Timezone('server'),
71 "timezone is GMT which one is alias for UTC");
73 RT->Config->Set( Timezone => '' );
74 is($date->Timezone('user'),
76 "user's and server's timzones are not defined, so UTC");
77 is($date->Timezone('server'),
79 "timezone of the server is not defined so UTC");
81 RT->Config->Set( Timezone => 'UTC' );
85 my $date = RT::Date->new(RT->SystemUser);
86 is($date->Unix, 0, "new date returns 0 in Unix format");
87 is($date->Get, '1970-01-01 00:00:00', "default is ISO format");
89 is($date->Get(Format =>'SomeBadFormat'),
90 '1970-01-01 00:00:00',
91 "don't know format, return ISO format");
92 } qr/Invalid date formatter/;
93 is($date->Get(Format =>'W3CDTF'),
94 '1970-01-01T00:00:00Z',
95 "W3CDTF format with defaults");
96 is($date->Get(Format =>'RFC2822'),
97 'Thu, 01 Jan 1970 00:00:00 +0000',
98 "RFC2822 format with defaults");
99 is($date->Get(Format =>'LocalizedDateTime'),
100 'Thu, Jan 1, 1970 12:00:00 AM',
101 "LocalizedDateTime format with defaults");
103 is($date->ISO(Time => 0),
105 "ISO format without time part");
106 is($date->W3CDTF(Time => 0),
108 "W3CDTF format without time part");
109 is($date->RFC2822(Time => 0),
111 "RFC2822 format without time part");
112 is($date->LocalizedDateTime(Time => 0),
114 "LocalizedDateTime format without time part");
116 is($date->ISO(Date => 0),
118 "ISO format without date part");
119 is($date->W3CDTF(Date => 0),
120 '1970-01-01T00:00:00Z',
121 "W3CDTF format is incorrect without date part");
122 is($date->RFC2822(Date => 0),
124 "RFC2822 format without date part");
125 is($date->LocalizedDateTime(Date => 0),
127 "LocalizedDateTime format without date part");
129 is($date->ISO(Date => 0, Seconds => 0),
131 "ISO format without date part and seconds");
132 is($date->W3CDTF(Date => 0, Seconds => 0),
134 "W3CDTF format without seconds, but we ship date part even if Date is false");
135 is($date->RFC2822(Date => 0, Seconds => 0),
137 "RFC2822 format without date part and seconds");
139 is($date->RFC2822(DayOfWeek => 0),
140 '01 Jan 1970 00:00:00 +0000',
141 "RFC2822 format without 'day of week' part");
142 is($date->RFC2822(DayOfWeek => 0, Date => 0),
144 "RFC2822 format without 'day of week' and date parts(corner case test)");
146 is($date->LocalizedDateTime(AbbrDay => 0),
147 'Thursday, Jan 1, 1970 12:00:00 AM',
148 "LocalizedDateTime format without abbreviation of day");
149 is($date->LocalizedDateTime(AbbrMonth => 0),
150 'Thu, January 1, 1970 12:00:00 AM',
151 "LocalizedDateTime format without abbreviation of month");
152 is($date->LocalizedDateTime(DateFormat => 'date_format_short'),
153 '1/1/70 12:00:00 AM',
154 "LocalizedDateTime format with non default DateFormat");
155 is($date->LocalizedDateTime(TimeFormat => 'time_format_short'),
156 'Thu, Jan 1, 1970 12:00 AM',
157 "LocalizedDateTime format with non default TimeFormat");
161 "the default format for the 'Date' method is ISO");
162 is($date->Date(Format => 'W3CDTF'),
164 "'Date' method, W3CDTF format");
165 is($date->Date(Format => 'RFC2822'),
167 "'Date' method, RFC2822 format");
168 is($date->Date(Time => 1),
170 "'Date' method doesn't pass through 'Time' argument");
171 is($date->Date(Date => 0),
173 "'Date' method overrides 'Date' argument");
177 "the default format for the 'Time' method is ISO");
178 is($date->Time(Format => 'W3CDTF'),
179 '1970-01-01T00:00:00Z',
180 "'Time' method, W3CDTF format, date part is required by w3c doc");
181 is($date->Time(Format => 'RFC2822'),
183 "'Time' method, RFC2822 format");
184 is($date->Time(Date => 1),
186 "'Time' method doesn't pass through 'Date' argument");
187 is($date->Time(Time => 0),
189 "'Time' method overrides 'Time' argument");
192 '1970-01-01 00:00:00',
193 "the default format for the 'DateTime' method is ISO");
194 is($date->DateTime(Format =>'W3CDTF'),
195 '1970-01-01T00:00:00Z',
196 "'DateTime' method, W3CDTF format");
197 is($date->DateTime(Format =>'RFC2822'),
198 'Thu, 01 Jan 1970 00:00:00 +0000',
199 "'DateTime' method, RFC2822 format");
200 is($date->DateTime(Date => 0, Time => 0),
201 '1970-01-01 00:00:00',
202 "the 'DateTime' method overrides both 'Date' and 'Time' arguments");
206 { # positive timezone
207 $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
208 my $date = RT::Date->new( $current_user );
209 $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-01-01 15:10:00' );
210 is($date->ISO( Timezone => 'user' ), '2005-01-01 18:10:00', "ISO");
211 is($date->W3CDTF( Timezone => 'user' ), '2005-01-01T18:10:00+03:00', "W3C DTF");
212 is($date->RFC2822( Timezone => 'user' ), 'Sat, 01 Jan 2005 18:10:00 +0300', "RFC2822");
215 $date = RT::Date->new( $current_user );
216 $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-07-01 15:10:00' );
217 is($date->ISO( Timezone => 'user' ), '2005-07-01 19:10:00', "ISO");
218 is($date->W3CDTF( Timezone => 'user' ), '2005-07-01T19:10:00+04:00', "W3C DTF");
219 is($date->RFC2822( Timezone => 'user' ), 'Fri, 01 Jul 2005 19:10:00 +0400', "RFC2822");
222 { # negative timezone
223 $current_user->UserObj->__Set( Field => 'Timezone', Value => 'America/New_York');
224 my $date = RT::Date->new( $current_user );
225 $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-01-01 15:10:00' );
226 is($date->ISO( Timezone => 'user' ), '2005-01-01 10:10:00', "ISO");
227 is($date->W3CDTF( Timezone => 'user' ), '2005-01-01T10:10:00-05:00', "W3C DTF");
228 is($date->RFC2822( Timezone => 'user' ), 'Sat, 01 Jan 2005 10:10:00 -0500', "RFC2822");
231 $date = RT::Date->new( $current_user );
232 $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-07-01 15:10:00' );
233 is($date->ISO( Timezone => 'user' ), '2005-07-01 11:10:00', "ISO");
234 is($date->W3CDTF( Timezone => 'user' ), '2005-07-01T11:10:00-04:00', "W3C DTF");
235 is($date->RFC2822( Timezone => 'user' ), 'Fri, 01 Jul 2005 11:10:00 -0400', "RFC2822");
240 my $date = RT::Date->new(RT->SystemUser);
241 $date->Set( Format => 'bad' );
242 is($date->Unix, 0, "bad format");
243 } qr{Unknown Date format: bad};
246 { # setting value via Unix method
247 my $date = RT::Date->new(RT->SystemUser);
249 is($date->ISO, '1970-01-01 00:00:01', "correct value");
251 foreach (undef, 0, ''){
253 is($date->ISO, '1970-01-01 00:00:01', "correct value");
255 $date->Set(Format => 'unix', Value => $_);
256 is($date->ISO, '1970-01-01 00:00:00', "Set a date to midnight 1/1/1970 GMT due to wrong call");
257 is($date->Unix, 0, "unix is 0 => unset");
261 my $year = (localtime(time))[5] + 1900;
264 my $date = RT::Date->new(RT->SystemUser);
266 $date->Set(Format => 'ISO', Value => 'weird date');
267 } qr/Couldn't parse date 'weird date' as a ISO format/;
268 is($date->Unix, 0, "date was wrong => unix == 0");
270 # XXX: ISO format has more feature than we suport
271 # http://www.cl.cam.ac.uk/~mgk25/iso-time.html
273 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
274 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
276 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00+00');
277 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss+00");
279 $date->Set(Format => 'ISO', Value => '11-28 15:10:00');
280 is($date->ISO, $year .'-11-28 15:10:00', "DD-MM hh:mm:ss");
282 $date->Set(Format => 'ISO', Value => '11-28 15:10:00+00');
283 is($date->ISO, $year .'-11-28 15:10:00', "DD-MM hh:mm:ss+00");
285 $date->Set(Format => 'ISO', Value => '20051128151000');
286 is($date->ISO, '2005-11-28 15:10:00', "YYYYDDMMhhmmss");
288 $date->Set(Format => 'ISO', Value => '1128151000');
289 is($date->ISO, $year .'-11-28 15:10:00', "DDMMhhmmss");
291 $date->Set(Format => 'ISO', Value => '2005112815:10:00');
292 is($date->ISO, '2005-11-28 15:10:00', "YYYYDDMMhh:mm:ss");
294 $date->Set(Format => 'ISO', Value => '112815:10:00');
295 is($date->ISO, $year .'-11-28 15:10:00', "DDMMhh:mm:ss");
297 $date->Set(Format => 'ISO', Value => '2005-13-28 15:10:00');
298 is($date->Unix, 0, "wrong month value");
300 $date->Set(Format => 'ISO', Value => '2005-00-28 15:10:00');
301 is($date->Unix, 0, "wrong month value");
303 $date->Set(Format => 'ISO', Value => '1960-01-28 15:10:00');
304 is($date->Unix, 0, "too old, we don't support");
307 { # set+datemanip format(Time::ParseDate)
308 my $date = RT::Date->new(RT->SystemUser);
310 RT->Config->Set( Timezone => 'Europe/Moscow' );
311 $date->Set(Format => 'datemanip', Value => '2005-11-28 15:10:00');
312 is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
314 RT->Config->Set( Timezone => 'UTC' );
315 $date->Set(Format => 'datemanip', Value => '2005-11-28 15:10:00');
316 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
318 $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
319 $date = RT::Date->new( $current_user );
320 $date->Set(Format => 'datemanip', Value => '2005-11-28 15:10:00');
321 is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
324 { # set+unknown format(Time::ParseDate)
325 my $date = RT::Date->new(RT->SystemUser);
327 $date->Set(Format => 'unknown', Value => 'weird date');
328 } qr{Couldn't parse date 'weird date' by Time::ParseDate};
329 is($date->Unix, 0, "date was wrong");
331 RT->Config->Set( Timezone => 'Europe/Moscow' );
332 $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00');
333 is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
335 $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00', Timezone => 'utc' );
336 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
338 # test relative dates
340 set_fixed_time("2005-11-28T15:10:00Z");
341 $date->Set(Format => 'unknown', Value => 'now');
342 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
344 $date->Set(Format => 'unknown', Value => '1 day ago');
345 is($date->ISO, '2005-11-27 15:10:00', "YYYY-DD-MM hh:mm:ss");
349 RT->Config->Set( Timezone => 'UTC' );
350 $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00');
351 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
353 $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
354 $date = RT::Date->new( $current_user );
355 $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00');
356 is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
357 $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00', Timezone => 'server' );
358 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
359 $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00', Timezone => 'utc' );
360 is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
364 my $date = RT::Date->new(RT->SystemUser);
366 RT->Config->Set( Timezone => 'Europe/Moscow' );
367 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
368 $date->SetToMidnight;
369 is($date->ISO, '2005-11-28 00:00:00', "default is utc");
370 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
371 $date->SetToMidnight(Timezone => 'utc');
372 is($date->ISO, '2005-11-28 00:00:00', "utc context");
373 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
374 $date->SetToMidnight(Timezone => 'user');
375 is($date->ISO, '2005-11-27 21:00:00', "user context, user has no preference, fallback to server");
376 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
377 $date->SetToMidnight(Timezone => 'server');
378 is($date->ISO, '2005-11-27 21:00:00', "server context");
380 $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
381 $date = RT::Date->new( $current_user );
382 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
383 $date->SetToMidnight;
384 is($date->ISO, '2005-11-28 00:00:00', "default is utc");
385 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
386 $date->SetToMidnight(Timezone => 'utc');
387 is($date->ISO, '2005-11-28 00:00:00', "utc context");
388 $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
389 $date->SetToMidnight(Timezone => 'user');
390 is($date->ISO, '2005-11-27 21:00:00', "user context");
391 $date->SetToMidnight(Timezone => 'server');
392 is($date->ISO, '2005-11-27 21:00:00', "server context");
394 RT->Config->Set( Timezone => 'UTC' );
398 my $date = RT::Date->new(RT->SystemUser);
401 ok($date->Unix >= $time, 'close enough');
402 ok($date->Unix < $time+5, 'difference is less than five seconds');
406 my $date = RT::Date->new(RT->SystemUser);
410 is($date->ISO, '1970-01-01 00:00:00', "nothing changed");
411 $date->AddSeconds(0);
412 is($date->ISO, '1970-01-01 00:00:00', "nothing changed");
415 $date->AddSeconds(5);
416 is($date->ISO, '1970-01-01 00:00:05', "added five seconds");
417 $date->AddSeconds(-2);
418 is($date->ISO, '1970-01-01 00:00:03', "substracted two seconds");
421 $date->AddSeconds(3661);
422 is($date->ISO, '1970-01-01 01:01:01', "added one hour, minute and a second");
424 # XXX: TODO, doesn't work with Test::Warn
426 # local $TODO = "BUG or subject to change Date handling to support unix time <= 0";
428 # $date->AddSeconds(-2);
429 # ok($date->Unix > 0);
434 is($date->ISO, '1970-01-02 00:00:00', "added one day");
436 is($date->ISO, '1970-01-04 00:00:00', "added two days");
438 is($date->ISO, '1970-01-03 00:00:00', "substructed one day");
442 is($date->ISO, '1970-02-01 00:00:00', "added one month");
446 is($date->ISO, '1970-01-01 00:00:00', "added no days");
450 is($date->ISO, '1970-01-02 00:00:00', "added one day with no argument");
454 $current_user->UserObj->__Set( Field => 'Timezone', Value => '');
455 my $date = RT::Date->new( $current_user );
456 is($date->AsString, "Not set", "AsString returns 'Not set'");
458 RT->Config->Set( DateTimeFormat => '');
460 is($date->AsString, 'Thu Jan 01 00:00:01 1970', "correct string");
461 is($date->AsString(Date => 0), '00:00:01', "correct string");
462 is($date->AsString(Time => 0), 'Thu Jan 01 1970', "correct string");
463 is($date->AsString(Date => 0, Time => 0), 'Thu Jan 01 00:00:01 1970', "invalid input");
465 RT->Config->Set( DateTimeFormat => 'RFC2822' );
467 is($date->AsString, 'Thu, 01 Jan 1970 00:00:01 +0000', "correct string");
469 RT->Config->Set( DateTimeFormat => { Format => 'RFC2822', Seconds => 0 } );
471 is($date->AsString, 'Thu, 01 Jan 1970 00:00 +0000', "correct string");
472 is($date->AsString(Seconds => 1), 'Thu, 01 Jan 1970 00:00:01 +0000', "correct string");
476 my $date = RT::Date->new(RT->SystemUser);
478 is($date->DurationAsString(1), '1 sec', '1 sec');
479 is($date->DurationAsString(59), '59 sec', '59 sec');
480 is($date->DurationAsString(60), '1 min', '1 min');
481 is($date->DurationAsString(60*119), '119 min', '119 min');
482 is($date->DurationAsString(60*60*2-1), '120 min', '120 min');
483 is($date->DurationAsString(60*60*2), '2 hours', '2 hours');
484 is($date->DurationAsString(60*60*48-1), '48 hours', '48 hours');
485 is($date->DurationAsString(60*60*48), '2 days', '2 days');
486 is($date->DurationAsString(60*60*24*14-1), '14 days', '14 days');
487 is($date->DurationAsString(60*60*24*14), '2 weeks', '2 weeks');
488 is($date->DurationAsString(60*60*24*7*8-1), '8 weeks', '8 weeks');
489 is($date->DurationAsString(60*60*24*61), '2 months', '2 months');
490 is($date->DurationAsString(60*60*24*365-1), '12 months', '12 months');
491 is($date->DurationAsString(60*60*24*366), '1 years', '1 years');
493 is($date->DurationAsString(-1), '1 sec ago', '1 sec ago');
497 my $date = RT::Date->new(RT->SystemUser);
498 is($date->DiffAsString(1), '', 'no diff, wrong input');
499 is($date->DiffAsString(-1), '', 'no diff, wrong input');
500 is($date->DiffAsString('qwe'), '', 'no diff, wrong input');
503 is($date->DiffAsString(-1), '', 'no diff, wrong input');
505 is($date->DiffAsString(3), '1 sec ago', 'diff: 1 sec ago');
506 is($date->DiffAsString(1), '1 sec', 'diff: 1 sec');
508 my $ndate = RT::Date->new(RT->SystemUser);
509 is($date->DiffAsString($ndate), '', 'no diff, wrong input');
511 is($date->DiffAsString($ndate), '1 sec ago', 'diff: 1 sec ago');
515 my $date = RT::Date->new(RT->SystemUser);
517 my $diff = $date->Diff;
518 ok($diff <= 0, 'close enought');
519 ok($diff > -5, 'close enought');
523 my $date = RT::Date->new(RT->SystemUser);
525 my $diff = $date->AgeAsString;
526 like($diff, qr/^(0 sec|[1-5] sec ago)$/, 'close enought');
530 my $date = RT::Date->new(RT->SystemUser);
531 is($date->GetWeekday(7), '', '7 and greater are invalid');
532 is($date->GetWeekday(6), 'Sat', '6 is Saturday');
533 is($date->GetWeekday(0), 'Sun', '0 is Sunday');
534 is($date->GetWeekday(-1), 'Sat', '-1 is Saturday');
535 is($date->GetWeekday(-7), 'Sun', '-7 is Sunday');
536 is($date->GetWeekday(-8), '', '-8 and lesser are invalid');
540 my $date = RT::Date->new(RT->SystemUser);
541 is($date->GetMonth(12), '', '12 and greater are invalid');
542 is($date->GetMonth(11), 'Dec', '11 is December');
543 is($date->GetMonth(0), 'Jan', '0 is January');
544 is($date->GetMonth(-1), 'Dec', '11 is December');
545 is($date->GetMonth(-12), 'Jan', '0 is January');
546 is($date->GetMonth(-13), '', '-13 and lesser are invalid');
550 # set unknown format: edge cases
551 my $date = RT::Date->new(RT->SystemUser);
552 $date->Set( Value => 0, Format => 'unknown' );
553 is( $date->Unix(), 0, "unix is 0 with Value => 0, Format => 'unknown'" );
555 $date->Set( Value => '', Format => 'unknown' );
556 is( $date->Unix(), 0, "unix is 0 with Value => '', Format => 'unknown'" );
558 $date->Set( Value => ' ', Format => 'unknown' );
559 is( $date->Unix(), 0, "unix is 0 with Value => ' ', Format => 'unknown'" );
563 #TODO: RFC2822, W3CDTF with Timezones