docs
[pspp] / tests / data / test-date-input.py
1 #! /usr/bin/env python
2 # Copyright (C) 2020  Free Software Foundation
3
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 import re
18 import sys
19
20 fmt_name = sys.argv[1]
21 templates = sys.argv[2:]
22
23 dates = (#yyyy  mm  dd  jjj  HH  MM  SS
24          (1648,  6, 10, 162,  0,  0,  0),
25          (1680,  6, 30, 182,  4, 50, 38),
26          (1716,  7, 24, 206, 12, 31, 35),
27          (1768,  6, 19, 171, 12, 47, 53),
28          (1819,  8,  2, 214,  1, 26,  0),
29          (1839,  3, 27,  86, 20, 58, 11),
30          (1903,  4, 19, 109,  7, 36,  5),
31          (1929,  8, 25, 237, 15, 43, 49),
32          (1941,  9, 29, 272,  4, 25,  9),
33          (1943,  4, 19, 109,  6, 49, 27),
34          (1943, 10,  7, 280,  2, 57, 52),
35          (1992,  3, 17,  77, 16, 45, 44),
36          (1996,  2, 25,  56, 21, 30, 57),
37          (1941,  9, 29, 272,  4, 25,  9),
38          (1943,  4, 19, 109,  6, 49, 27),
39          (1943, 10,  7, 280,  2, 57, 52),
40          (1992,  3, 17,  77, 16, 45, 44),
41          (1996,  2, 25,  56, 21, 30, 57),
42          (2038, 11, 10, 314, 22, 30,  4),
43          (2094,  7, 18, 199,  1, 56, 51))
44
45 syntax_file = open('%s.sps' % fmt_name, 'w')
46 syntax_file.write('''\
47 SET EPOCH 1930.
48 DATA LIST NOTABLE FILE='%(fmt_name)s.input'/%(fmt_name)s 1-40 (%(fmt_name)s).
49 PRINT OUTFILE='%(fmt_name)s.output'/%(fmt_name)s (F16.2).
50 EXECUTE.
51 ''' % {'fmt_name': fmt_name})
52 syntax_file.close()
53
54 expout_file = open('expout', 'w')
55 input_file = open('%s.input' % fmt_name, 'w')
56
57 def is_leap_year(y):
58     return y % 4 == 0 and (y % 100 != 0 or y % 400 == 0)
59
60 n = 0
61 def print_all_formats(date, template, formatted, exp_y, exp_m, exp_d,
62                       exp_time, exp_sign):
63     if template != '':
64         global n
65         n += 1
66         year, month, day, julian, hour, minute, second = date
67         quarter = (month - 1) // 3 + 1
68         week = (julian - 1) // 7 + 1
69         if year >= 1930 and year < 2030:
70             years = ('%d' % year, '%d' % (year % 100))
71         else:
72             years = ('%d' % year,)
73
74         c = template[0]
75         template = template[1:]
76         if c == 'd':
77             for f in ('%d', '%02d'):
78                 print_all_formats(date, template, formatted + (f % day),
79                                   exp_y, exp_m, day, exp_time, exp_sign)
80         elif c == 'm':
81             for f in ('%d' % month,
82                       '%02d' % month,
83                       ('i', 'ii', 'iii', 'iv', 'v', 'vi',
84                        'vii', 'viii', 'ix', 'x', 'xi', 'xii')[month - 1],
85                       ('I', 'II', 'III', 'IV', 'V', 'VI',
86                        'VII', 'VIII', 'IX', 'X', 'XI', 'XII')[month - 1],
87                       ('jan', 'feb', 'mar', 'apr', 'may', 'jun',
88                        'jul', 'aug', 'sep', 'oct', 'nov', 'dec')[month - 1],
89                       ('JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN',
90                        'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC')[month - 1],
91                       ('january', 'february', 'march',
92                        'april', 'may', 'june',
93                        'july', 'august', 'september',
94                        'october', 'november', 'december')[month - 1],
95                       ('JANUARY', 'FEBRUARY', 'MARCH',
96                        'APRIL', 'MAY', 'JUNE',
97                        'JULY', 'AUGUST', 'SEPTEMBER',
98                        'OCTOBER', 'NOVEMBER', 'DECEMBER')[month - 1]):
99                 print_all_formats(date, template, formatted + f,
100                                   exp_y, month, exp_d, exp_time, exp_sign)
101         elif c == 'y':
102             for f in years:
103                 print_all_formats(date, template, formatted + f,
104                                   year, exp_m, exp_d, exp_time, exp_sign)
105         elif c == 'j':
106             for f in years:
107                 print_all_formats(date, template,
108                                   formatted + f + ('%03d' % julian),
109                                   year, month, day, exp_time, exp_sign)
110         elif c == 'q':
111             print_all_formats(date, template, formatted + ('%d' % quarter),
112                               exp_y, (quarter - 1) * 3 + 1, 1,
113                               exp_time, exp_sign)
114         elif c == 'w':
115             exp_m = month
116             exp_d = day - (julian - 1) % 7
117             if exp_d < 1:
118                 exp_m -= 1
119                 exp_d += (31, 29 if is_leap_year(year) else 28, 31,
120                           30, 31, 30, 31, 31, 30, 31, 30, 31)[exp_m]
121             print_all_formats(date, template, formatted + ('%d' % week),
122                               exp_y, exp_m, exp_d, exp_time, exp_sign)
123
124         elif c == 'H':
125             for f in ('%d', '%02d'):
126                 print_all_formats(date, template, formatted + (f % hour),
127                                   exp_y, exp_m, exp_d, exp_time + hour * 3600,
128                                   exp_sign)
129         elif c == 'M':
130             for f in ('%d', '%02d'):
131                 print_all_formats(date, template, formatted + (f % minute),
132                                   exp_y, exp_m, exp_d, exp_time + minute * 60,
133                                   exp_sign)
134         elif c == 'S':
135             for f in ('%d', '%02d'):
136                 print_all_formats(date, template, formatted + (f % second),
137                                   exp_y, exp_m, exp_d, exp_time + second,
138                                   exp_sign)
139         elif c == '-':
140             for f in ' -.,/':
141                 print_all_formats(date, template, formatted + f,
142                                   exp_y, exp_m, exp_d, exp_time,
143                                   exp_sign)
144         elif c == ':':
145             for f in ' :':
146                 print_all_formats(date, template, formatted + f,
147                                   exp_y, exp_m, exp_d, exp_time,
148                                   exp_sign)
149         elif c == ' ':
150             print_all_formats(date, template, formatted + ' ',
151                               exp_y, exp_m, exp_d, exp_time,
152                               exp_sign)
153         elif c == 'Q' or c == 'W':
154             infix = 'q' if c == 'Q' else 'wk'
155             for before in (' ', ''):
156                 for middle in (infix, infix.upper()):
157                     for after in (' ', ''):
158                         print_all_formats(date, template,
159                                           formatted + before + middle + after,
160                                           exp_y, exp_m, exp_d, exp_time,
161                                           exp_sign)
162         elif c == '+':
163             for f in ('', '+', '-'):
164                 print_all_formats(date, template, formatted + f,
165                                   exp_y, exp_m, exp_d, exp_time,
166                                   f)
167         else:
168             assert False
169     else:
170         # Write the formatted value to fmt_name.input.
171         input_file.write('%s\n' % formatted)
172
173         # Write the expected value to 'expout'.
174         assert exp_y >= 1582 and exp_y <= 2100
175         assert exp_m >= 1 and exp_m <= 12
176         assert exp_d >= 1 and exp_d <= 31
177         EPOCH = -577734         # 14 Oct 1582
178         expected = (EPOCH - 1
179                     + 365 * (exp_y - 1)
180                     + (exp_y - 1) // 4
181                     - (exp_y - 1) // 100
182                     + (exp_y - 1) // 400
183                     + (367 * exp_m - 362) // 12
184                     + (0 if exp_m <= 2
185                        else -1 if exp_m >= 2 and is_leap_year(exp_y)
186                        else -2)
187                     + exp_d) * 86400
188         if exp_sign == '-' and expected > 0:
189             expected -= exp_time
190         else:
191             expected += exp_time
192         expected_s = '%17.2f\n' % expected
193         expected_s = expected_s.replace(' 0.', '  .')
194         expout_file.write(expected_s)
195
196
197 for template in templates:
198     for date in dates:
199         print_all_formats(date, template, '', 0, 0, 1, 0, '')
200