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