summaryrefslogtreecommitdiff
path: root/t/03-date-handling.t
blob: be252e9d54f5f2e7ab790cee05a4182c85f17caf (plain)
  1. #!/usr/bin/perl
  2. #
  3. # Note: This file assumes good dates, SL behaviour with bad dates is undefined
  4. #
  5. use strict;
  6. use warnings;
  7. use Test::More 'no_plan';
  8. use Math::BigFloat;
  9. use LedgerSMB::Sysconfig;
  10. use LedgerSMB::Form;
  11. use LedgerSMB::Locale;
  12. my $form = new Form;
  13. my $locale_en = LedgerSMB::Locale->get_handle('en');
  14. my $locale_es = LedgerSMB::Locale->get_handle('es');
  15. my %myconfig;
  16. ok(defined $form);
  17. isa_ok($form, 'Form');
  18. $form->{dbh} = ${LedgerSMB::Sysconfig::GLOBALDBH};
  19. my @formats = ( ['mm-dd-yy', '-', 2, '02-29-00', '03-01-00'],
  20. ['mm/dd/yy', '/', 2, '02/29/00', '03/01/00'],
  21. ['dd-mm-yy', '-', 2, '29-02-00', '01-03-00'],
  22. ['dd/mm/yy', '/', 2, '29/02/00', '01/03/00'],
  23. ['dd.mm.yy', '.', 2, '29.02.00', '01.03.00'],
  24. # ['yyyymmdd', '', 4, '20000229', '20000301'],
  25. ['yyyy-mm-dd', '-', 4, '2000-02-29', '2000-03-01']);
  26. my @months = ('January', 'February', 'March', 'April', 'May ', 'June',
  27. 'July', 'August', 'September', 'October', 'November', 'December');
  28. my %month_num = ('01' => '31', '02' => '28', '03' => '31', '04' => '30',
  29. '05' => '31', '06' => '30', '07' => '31', '08' => '31',
  30. '09' => '30', '10' => '31', '11' => '30', '12' => '31');
  31. my $today = `date +\%F`;
  32. chomp $today;
  33. my %today_parts;
  34. $today_parts{'yyyy'} = `date +\%Y`;
  35. $today_parts{'yy'} = $today_parts{'yyyy'};
  36. $today_parts{'yy'} =~ s/^..//;
  37. $today_parts{'mm'} = `date +\%m`;
  38. $today_parts{'dd'} = `date +\%d`;
  39. chomp $today_parts{'yyyy'};
  40. chomp $today_parts{'yy'};
  41. chomp $today_parts{'mm'};
  42. chomp $today_parts{'dd'};
  43. # $locale->date checks
  44. # Note that $locale->date assumes the year range 2000-2099
  45. # Note that $locale->date does not perform language-specific long forms
  46. # Note that $locale->date also takes in yyyymmdd
  47. foreach my $format (0 .. $#formats) {
  48. %myconfig = (dateformat => $formats[$format][0]);
  49. my $fmt = $formats[$format][0];
  50. my $sep = $formats[$format][1];
  51. my $yearcount = $formats[$format][2];
  52. my $result = $formats[$format][3];
  53. $result =~ s/^(.*)(20)?00(.*)$/${1}2000${3}/ if $yearcount == 2;
  54. cmp_ok($locale_en->date(\%myconfig), 'eq',
  55. '', "date, $fmt: empty string");
  56. cmp_ok($locale_en->date(\%myconfig, $formats[$format][3]), 'eq',
  57. $result, "date, $fmt: short");
  58. cmp_ok($locale_en->date(\%myconfig, '20000229'), 'eq',
  59. $result, "date, $fmt: chopped");
  60. for my $mm (1 .. 12) {
  61. my $start = $fmt;
  62. my $temp = sprintf('%02d', $mm);
  63. my $month_en = $locale_en->text($months[$mm - 1]);
  64. my $month_es = $locale_es->text($months[$mm - 1]);
  65. $start =~ s/dd/29/;
  66. $start =~ s/yyyy/2000/;
  67. $start =~ s/yy/00/;
  68. $start =~ s/mm/$temp/;
  69. cmp_ok($locale_es->date(\%myconfig, $start, 1), 'eq',
  70. "$month_es 29 2000", "date, $start, $fmt: long, es");
  71. cmp_ok($locale_en->date(\%myconfig, $start, 1), 'eq',
  72. "$month_en 29 2000", "date, $start, $fmt: long, en");
  73. }
  74. }
  75. # $form->current_date checks
  76. # Note that $form->current_date always uses the database
  77. # Note that $form->current_date can take four digit years with all formats
  78. # Note that $form->current_date will always accept a dateformat of 'yyyymmdd'
  79. foreach my $format (0 .. $#formats) {
  80. %myconfig = (dateformat => $formats[$format][0]);
  81. my $fmt = $formats[$format][0];
  82. my $sep = $formats[$format][1];
  83. my $yearcount = $formats[$format][2];
  84. my $tv = $fmt;
  85. $tv =~ s/(yy)?yy/$today_parts{'yyyy'}/;
  86. $tv =~ s/mm/$today_parts{'mm'}/;
  87. $tv =~ s/dd/$today_parts{'dd'}/;
  88. is($form->current_date(\%myconfig),
  89. $today, "current_date, $fmt: $today");
  90. is($form->current_date(\%myconfig, $formats[$format][3]),
  91. '2000-02-29', "current_date, $fmt: 2000-02-29");
  92. is($form->current_date(\%myconfig, $formats[$format][3], 1),
  93. '2000-03-01', "current_date, $fmt: 2000-03-01");
  94. is($form->current_date(\%myconfig, $tv),
  95. $today, "current_date, $fmt: $tv");
  96. $tv = "$today_parts{'yyyy'}$today_parts{'mm'}$today_parts{'dd'}";
  97. is($form->current_date(\%myconfig, $tv),
  98. $today, "current_date, $fmt: $tv");
  99. }
  100. # $form->datetonum checks
  101. # Note that $form->datetonum assumes the year range 2000-2099
  102. # Note that $form->datetonum is identity if there is no date or non-digit
  103. foreach my $format (0 .. $#formats) {
  104. %myconfig = (dateformat => $formats[$format][0]);
  105. my $fmt = $formats[$format][0];
  106. my $sep = $formats[$format][1];
  107. my $yearcount = $formats[$format][2];
  108. cmp_ok($form->datetonum(\%myconfig, $formats[$format][3]), 'eq',
  109. '20000229', "datetonum, $fmt");
  110. }
  111. cmp_ok($form->datetonum(\%myconfig), 'eq', '', "datetonum, empty string");
  112. cmp_ok($form->datetonum(\%myconfig, '1234'), 'eq', '1234', "datetonum, 1234");
  113. # $form->split_date checks
  114. # Note that $form->split_date assumes the year range 2000-2099
  115. # Note that $form->split_date only outputs two digit years
  116. # Note that $form->split_date if a date provided without non-digit, identity
  117. foreach my $format (0 .. $#formats) {
  118. %myconfig = (dateformat => $formats[$format][0]);
  119. my $fmt = $formats[$format][0];
  120. my $sep = $formats[$format][1];
  121. my $yearcount = $formats[$format][2];
  122. my @output = $form->split_date($fmt, $formats[$format][3]);
  123. my $rv = $fmt;
  124. $rv =~ s/\Q$sep\E//g;
  125. $rv =~ s/(yy)?yy/$output[1]/;
  126. $rv =~ s/mm/$output[2]/;
  127. $rv =~ s/dd/$output[3]/;
  128. cmp_ok($output[1], 'eq', '00', "split_date specified, year");
  129. cmp_ok($output[2], 'eq', '02', "split_date specified, month");
  130. cmp_ok($output[3], 'eq', '29', "split_date specified, day");
  131. cmp_ok($output[0], 'eq', $rv, "split_date specified, unit");
  132. @output = $form->split_date($fmt);
  133. $rv = $fmt;
  134. $rv =~ s/\Q$sep\E//g;
  135. $rv =~ s/(yy)?yy/$output[1]/;
  136. $rv =~ s/mm/$output[2]/;
  137. $rv =~ s/dd/$output[3]/;
  138. my $tv = $fmt;
  139. $tv =~ s/\Q$sep\E//g;
  140. $tv =~ s/(yy)?yy/$today_parts{'yy'}/;
  141. $tv =~ s/mm/$today_parts{'mm'}/;
  142. $tv =~ s/dd/$today_parts{'dd'}/;
  143. cmp_ok($output[1], 'eq', $today_parts{'yy'},
  144. "split_date unspecified, year");
  145. cmp_ok($output[2], 'eq', $today_parts{'mm'},
  146. "split_date unspecified, month");
  147. cmp_ok($output[3], 'eq', $today_parts{'dd'},
  148. "split_date unspecified, day");
  149. @output = $form->split_date($fmt, '12345');
  150. cmp_ok($output[0], 'eq', '12345',
  151. 'split_date, 12345');
  152. }
  153. # $form->format_date checks
  154. # Note that $form->format_date always outputs four digit years
  155. foreach my $format (0 .. $#formats) {
  156. $form->{db_dateformat} = $formats[$format][0];
  157. my $fmt = $formats[$format][0];
  158. my $sep = $formats[$format][1];
  159. my $yearcount = $formats[$format][2];
  160. my $results = $fmt;
  161. $results =~ s/(yy)?yy/2000/;
  162. $results =~ s/mm/02/;
  163. $results =~ s/dd/29/;
  164. cmp_ok($form->format_date('2000-02-29'), 'eq',
  165. $results, "format_date, $fmt, ISO");
  166. cmp_ok($form->format_date($formats[$format][3]), 'eq',
  167. $formats[$format][3], "format_date, $fmt, non-ISO");
  168. }
  169. # $form->from_to checks
  170. # Note that $form->from_to requires $form->format_date
  171. # Note that $form->from_to outputs four digit years
  172. # Note that $form->from_to outputs 1999-12-31 (formatted) if no input given
  173. # Note that $form->from_to outputs the last day of the previous year if only year given
  174. # Note that $form->from_to outputs the last day of the chosen month if month given
  175. # Note that $form->from_to $interval of 0 is current day
  176. # Note that $form->from_to $interval is an integral quantity of months
  177. # Note that $form->from_to will fail if ($interval + $month) > 22
  178. # (2 + 23), 25 - 12, 13 - 1, 12
  179. foreach my $format (0 .. $#formats) {
  180. $form->{db_dateformat} = $formats[$format][0];
  181. my $fmt = $formats[$format][0];
  182. my $sep = $formats[$format][1];
  183. my $yearcount = $formats[$format][2];
  184. my $results = $fmt;
  185. $results =~ s/(yy)?yy/1999/;
  186. $results =~ s/mm/12/;
  187. $results =~ s/dd/31/;
  188. cmp_ok($form->from_to(), 'eq',
  189. $results, "from_to, $fmt, unspecified");
  190. $results =~ s/1999/2006/;
  191. cmp_ok($form->from_to('07'), 'eq',
  192. $results, "from_to, $fmt, 07");
  193. cmp_ok($form->from_to('2007'), 'eq',
  194. $results, "from_to, $fmt, 2007");
  195. $results =~ s/2006/2007/;
  196. $results =~ s/12/05/;
  197. cmp_ok($form->from_to('07', '05'), 'eq',
  198. $results, "from_to, $fmt, 07-05");
  199. cmp_ok($form->from_to('2007', '05'), 'eq',
  200. $results, "from_to, $fmt, 2007-05");
  201. $results =~ s/05/02/;
  202. $results =~ s/31/28/;
  203. cmp_ok($form->from_to('07', '02'), 'eq',
  204. $results, "from_to, $fmt, 07-02");
  205. cmp_ok($form->from_to('2007', '02'), 'eq',
  206. $results, "from_to, $fmt, 2007-02");
  207. $results =~ s/2007/2000/;
  208. $results =~ s/28/29/;
  209. cmp_ok($form->from_to('00', '02'), 'eq',
  210. $results, "from_to, $fmt, 00-02 leap day");
  211. cmp_ok($form->from_to('2000', '02'), 'eq',
  212. $results, "from_to, $fmt, 2000-02 leap day");
  213. $results =~ s/29/31/;
  214. $results =~ s/02/01/;
  215. cmp_ok($form->from_to('00', '01'), 'eq',
  216. $results, "from_to, $fmt, 00-01 year edge");
  217. cmp_ok($form->from_to('2000', '01'), 'eq',
  218. $results, "from_to, $fmt, 2000-01 year edge");
  219. $results =~ s/01/12/;
  220. cmp_ok($form->from_to('00', '12'), 'eq',
  221. $results, "from_to, $fmt, 00-12 year edge");
  222. cmp_ok($form->from_to('2000', '12'), 'eq',
  223. $results, "from_to, $fmt, 2000-12 year edge");
  224. $results =~ s/12/02/;
  225. $results =~ s/31/29/;
  226. cmp_ok($form->from_to('00', '02', '1'), 'eq',
  227. $results, "from_to, $fmt, 00-02, 1 interval");
  228. cmp_ok($form->from_to('2000', '02', '1'), 'eq',
  229. $results, "from_to, $fmt, 2000-02, 1 interval");
  230. $results =~ s/29/28/;
  231. my $month;
  232. my $lastmonth;
  233. for (2 .. 11) {
  234. $month = sprintf '%02d', $_ + 1;
  235. $lastmonth = sprintf '%02d', $_;
  236. $results =~ s/$lastmonth/$month/;
  237. $results =~ s/$month_num{$lastmonth}/$month_num{$month}/;
  238. cmp_ok($form->from_to('00', '02', $_), 'eq',
  239. $results, "from_to, $fmt, 00-02, $_ interval");
  240. cmp_ok($form->from_to('2000', '02', $_), 'eq',
  241. $results, "from_to, $fmt, 2000-02, $_ interval");
  242. }
  243. $results =~ s/2000/2001/;
  244. for (0 .. 10) {
  245. $month = sprintf '%02d', $_ + 1;
  246. $lastmonth = sprintf '%02d', $_;
  247. $lastmonth = '12' if $lastmonth eq '00';
  248. $results =~ s/([^0])$lastmonth/${1}$month/;
  249. $results =~ s/^$lastmonth/$month/;
  250. $results =~ s/$month_num{$lastmonth}/$month_num{$month}/;
  251. cmp_ok($form->from_to('00', '02', $_ + 12), 'eq',
  252. $results, "from_to, $fmt, 00-02, $_ + 12 interval");
  253. cmp_ok($form->from_to('2000', '02', $_ + 12), 'eq',
  254. $results, "from_to, $fmt, 2000-02, $_ + 12 interval");
  255. }
  256. $results =~ s/2001/$today_parts{'yyyy'}/;
  257. $results =~ s/11/$today_parts{'mm'}/;
  258. $results =~ s/30/$today_parts{'dd'}/;
  259. cmp_ok($form->from_to('00', '02', '0'), 'eq',
  260. $results, "from_to, $fmt, 00-02, 0 interval (today)");
  261. cmp_ok($form->from_to('2000', '02', '0'), 'eq',
  262. $results, "from_to, $fmt, 2000-02, 0 interval (today)");
  263. }
  264. # $form->add_date checks
  265. # returns undef if no date passed
  266. # valid units: days, weeks, months, years
  267. # all uses in LSMB use days unit
  268. # has no error handling capabilities
  269. foreach my $format (0 .. $#formats) {
  270. $form->{db_dateformat} = $formats[$format][0];
  271. %myconfig = (dateformat => $formats[$format][0]);
  272. my $fmt = $formats[$format][0];
  273. my $sep = $formats[$format][1];
  274. my $yearcount = $formats[$format][2];
  275. my $start = $fmt;
  276. $start =~ s/(yy)?yy/2000/;
  277. $start =~ s/mm/01/;
  278. $start =~ s/dd/29/;
  279. my $results = $start;
  280. $results =~ s/29/30/;
  281. cmp_ok($form->add_date(\%myconfig, $start, 1, 'days'), 'eq',
  282. $results, "add_date, $fmt, 1 days, 2000-01-29");
  283. $results =~ s/30/31/;
  284. cmp_ok($form->add_date(\%myconfig, $start, 2, 'days'), 'eq',
  285. $results, "add_date, $fmt, 2 days, 2000-01-29");
  286. $results =~ s/31/05/;
  287. $results =~ s/01/02/;
  288. cmp_ok($form->add_date(\%myconfig, $start, 1, 'weeks'), 'eq',
  289. $results, "add_date, $fmt, 1 weeks, 2000-01-29");
  290. $results =~ s/05/12/;
  291. cmp_ok($form->add_date(\%myconfig, $start, 2, 'weeks'), 'eq',
  292. $results, "add_date, $fmt, 2 weeks, 2000-01-29");
  293. $results =~ s/12/29/;
  294. cmp_ok($form->add_date(\%myconfig, $start, 1, 'months'), 'eq',
  295. $results, "add_date, $fmt, 1 months, 2000-01-29");
  296. $results =~ s/02/03/;
  297. cmp_ok($form->add_date(\%myconfig, $start, 2, 'months'), 'eq',
  298. $results, "add_date, $fmt, 2 months, 2000-01-29");
  299. $results = $start;
  300. $results =~ s/01/11/;
  301. cmp_ok($form->add_date(\%myconfig, $start, 10, 'months'), 'eq',
  302. $results, "add_date, $fmt, 10 months, 2000-01-29");
  303. $results = $start;
  304. $results =~ s/01/12/;
  305. cmp_ok($form->add_date(\%myconfig, $start, 11, 'months'), 'eq',
  306. $results, "add_date, $fmt, 11 months, 2000-01-29");
  307. $results = $start;
  308. $results =~ s/2000/2001/;
  309. cmp_ok($form->add_date(\%myconfig, $start, 12, 'months'), 'eq',
  310. $results, "add_date, $fmt, 12 months, 2000-01-29");
  311. cmp_ok($form->add_date(\%myconfig, $start, 1, 'years'), 'eq',
  312. $results, "add_date, $fmt, 1 years, 2000-01-29");
  313. $results =~ s/2001/2002/;
  314. cmp_ok($form->add_date(\%myconfig, $start, 2, 'years'), 'eq',
  315. $results, "add_date, $fmt, 2 years, 2000-01-29");
  316. }
  317. cmp_ok($form->add_date(\%myconfig, '20000129', 2, 'years'), 'eq',
  318. '20020129', 'add_date, yyyymmdd, 2 years, 20000129');
  319. ok(!defined $form->add_date(\%myconfig),
  320. 'add_date, undef if no date');