getdate: correctly interpret "next monday" when run on a Monday
[pspp] / tests / test-getdate.c
1 /* Test of getdate() function.
2    Copyright (C) 2008, 2009 Free Software Foundation, Inc.
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, or (at your option)
7    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, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Simon Josefsson <simon@josefsson.org>, 2008.  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "progname.h"
27
28 #include "getdate.h"
29
30 #define ASSERT(expr)                                                    \
31   do                                                                    \
32     {                                                                   \
33       if (!(expr))                                                      \
34         {                                                               \
35           fprintf (stderr, "%s:%d: assertion failed\n",                 \
36                    __FILE__, __LINE__);                                 \
37           fflush (stderr);                                              \
38           abort ();                                                     \
39         }                                                               \
40     }                                                                   \
41   while (0)
42
43 #ifdef DEBUG
44 #define LOG(str, now, res)                                              \
45   printf ("string `%s' diff %d %d\n",                   \
46           str, res.tv_sec - now.tv_sec, res.tv_nsec - now.tv_nsec);
47 #else
48 #define LOG(str, now, res) (void) 0
49 #endif
50
51 static const char* const day_table[] =
52 {
53   "SUNDAY",
54   "MONDAY",
55   "TUESDAY",
56   "TUES",
57   "WEDNESDAY",
58   "WEDNES",
59   "THURSDAY",
60   "THUR",
61   "THURS",
62   "FRIDAY",
63   "SATURDAY",
64   NULL
65 };
66
67 int
68 main (int argc, char **argv)
69 {
70   struct timespec result;
71   struct timespec result2;
72   struct timespec now;
73   const char *p;
74   int i;
75
76   set_program_name (argv[0]);
77
78   now.tv_sec = 4711;
79   now.tv_nsec = 1267;
80   p = "now";
81   ASSERT (get_date (&result, p, &now));
82   LOG (p, now, result);
83   ASSERT (now.tv_sec == result.tv_sec && now.tv_nsec == result.tv_nsec);
84
85   now.tv_sec = 4711;
86   now.tv_nsec = 1267;
87   p = "tomorrow";
88   ASSERT (get_date (&result, p, &now));
89   LOG (p, now, result);
90   ASSERT (now.tv_sec + 24 * 60 * 60 == result.tv_sec
91           && now.tv_nsec == result.tv_nsec);
92
93   now.tv_sec = 4711;
94   now.tv_nsec = 1267;
95   p = "yesterday";
96   ASSERT (get_date (&result, p, &now));
97   LOG (p, now, result);
98   ASSERT (now.tv_sec - 24 * 60 * 60 == result.tv_sec
99           && now.tv_nsec == result.tv_nsec);
100
101   now.tv_sec = 4711;
102   now.tv_nsec = 1267;
103   p = "4 hours";
104   ASSERT (get_date (&result, p, &now));
105   LOG (p, now, result);
106   ASSERT (now.tv_sec + 4 * 60 * 60 == result.tv_sec
107           && now.tv_nsec == result.tv_nsec);
108
109   /* test if timezone is not being ignored for day offset */
110   now.tv_sec = 4711;
111   now.tv_nsec = 1267;
112   p = "UTC+400 +24 hours";
113   ASSERT (get_date (&result, p, &now));
114   LOG (p, now, result);
115   p = "UTC+400 +1 day";
116   ASSERT (get_date (&result2, p, &now));
117   LOG (p, now, result2);
118   ASSERT (result.tv_sec == result2.tv_sec
119           && result.tv_nsec == result2.tv_nsec);
120
121   /* test if several time zones formats are handled same way */
122   now.tv_sec = 4711;
123   now.tv_nsec = 1267;
124   p = "UTC+14:00";
125   ASSERT (get_date (&result, p, &now));
126   LOG (p, now, result);
127   p = "UTC+14";
128   ASSERT (get_date (&result2, p, &now));
129   LOG (p, now, result2);
130   ASSERT (result.tv_sec == result2.tv_sec
131           && result.tv_nsec == result2.tv_nsec);
132   p = "UTC+1400";
133   ASSERT (get_date (&result2, p, &now));
134   LOG (p, now, result2);
135   ASSERT (result.tv_sec == result2.tv_sec
136           && result.tv_nsec == result2.tv_nsec);
137
138   now.tv_sec = 4711;
139   now.tv_nsec = 1267;
140   p = "UTC-14:00";
141   ASSERT (get_date (&result, p, &now));
142   LOG (p, now, result);
143   p = "UTC-14";
144   ASSERT (get_date (&result2, p, &now));
145   LOG (p, now, result2);
146   ASSERT (result.tv_sec == result2.tv_sec
147           && result.tv_nsec == result2.tv_nsec);
148   p = "UTC-1400";
149   ASSERT (get_date (&result2, p, &now));
150   LOG (p, now, result2);
151   ASSERT (result.tv_sec == result2.tv_sec
152           && result.tv_nsec == result2.tv_nsec);
153
154   now.tv_sec = 4711;
155   now.tv_nsec = 1267;
156   p = "UTC+0:15";
157   ASSERT (get_date (&result, p, &now));
158   LOG (p, now, result);
159   p = "UTC+0015";
160   ASSERT (get_date (&result2, p, &now));
161   LOG (p, now, result2);
162   ASSERT (result.tv_sec == result2.tv_sec
163           && result.tv_nsec == result2.tv_nsec);
164
165   now.tv_sec = 4711;
166   now.tv_nsec = 1267;
167   p = "UTC-1:30";
168   ASSERT (get_date (&result, p, &now));
169   LOG (p, now, result);
170   p = "UTC-130";
171   ASSERT (get_date (&result2, p, &now));
172   LOG (p, now, result2);
173   ASSERT (result.tv_sec == result2.tv_sec
174           && result.tv_nsec == result2.tv_nsec);
175
176
177   /* TZ out of range should cause get_date failure */
178   now.tv_sec = 4711;
179   now.tv_nsec = 1267;
180   p = "UTC+25:00";
181   ASSERT (!get_date (&result, p, &now));
182
183         /* Check for several invalid countable dayshifts */
184   now.tv_sec = 4711;
185   now.tv_nsec = 1267;
186   p = "UTC+4:00 +40 yesterday";
187   ASSERT (!get_date (&result, p, &now));
188   p = "UTC+4:00 next yesterday";
189   ASSERT (!get_date (&result, p, &now));
190   p = "UTC+4:00 tomorrow ago";
191   ASSERT (!get_date (&result, p, &now));
192   p = "UTC+4:00 40 now ago";
193   ASSERT (!get_date (&result, p, &now));
194   p = "UTC+4:00 last tomorrow";
195   ASSERT (!get_date (&result, p, &now));
196   p = "UTC+4:00 -4 today";
197   ASSERT (!get_date (&result, p, &now));
198
199   /* And check correct usage of dayshifts */
200   now.tv_sec = 4711;
201   now.tv_nsec = 1267;
202   p = "UTC+400 tomorrow";
203   ASSERT (get_date (&result, p, &now));
204   LOG (p, now, result);
205   p = "UTC+400 +1 day";
206   ASSERT (get_date (&result2, p, &now));
207   LOG (p, now, result2);
208   ASSERT (result.tv_sec == result2.tv_sec
209           && result.tv_nsec == result2.tv_nsec);
210   now.tv_sec = 4711;
211   now.tv_nsec = 1267;
212   p = "UTC+400 yesterday";
213   ASSERT (get_date (&result, p, &now));
214   LOG (p, now, result);
215   p = "UTC+400 1 day ago";
216   ASSERT (get_date (&result2, p, &now));
217   LOG (p, now, result2);
218   ASSERT (result.tv_sec == result2.tv_sec
219           && result.tv_nsec == result2.tv_nsec);
220   now.tv_sec = 4711;
221   now.tv_nsec = 1267;
222   p = "UTC+400 now";
223   ASSERT (get_date (&result, p, &now));
224   LOG (p, now, result);
225   p = "UTC+400 +0 minutes"; /* silly, but simple "UTC+400" is different*/
226   ASSERT (get_date (&result2, p, &now));
227   LOG (p, now, result2);
228   ASSERT (result.tv_sec == result2.tv_sec
229           && result.tv_nsec == result2.tv_nsec);
230
231   /* Check that every 'last/next DAY' is in the past/future.  */
232   for (i = 0; day_table[i]; i++)
233     {
234       char tmp[32];
235       sprintf (tmp, "NEXT %s", day_table[i]);
236       now.tv_sec = 4711;
237       now.tv_nsec = 1267;
238       ASSERT (get_date (&result, tmp, &now));
239       LOG (tmp, now, result);
240       ASSERT (result.tv_sec > now.tv_sec
241               && result.tv_nsec == 0);
242
243       sprintf (tmp, "LAST %s", day_table[i]);
244       now.tv_sec = 4711;
245       now.tv_nsec = 1267;
246       ASSERT (get_date (&result, tmp, &now));
247       LOG (tmp, now, result);
248       ASSERT (result.tv_sec < now.tv_sec
249               && result.tv_nsec == 0);
250     }
251
252   p = "THURSDAY UTC+00";  /* The epoch was on Thursday.  */
253   now.tv_sec = 0;
254   now.tv_nsec = 0;
255   ASSERT (get_date (&result, p, &now));
256   LOG (p, now, result);
257   ASSERT (result.tv_sec == now.tv_sec
258           && result.tv_nsec == now.tv_nsec);
259
260   p = "FRIDAY UTC+00";
261   now.tv_sec = 0;
262   now.tv_nsec = 0;
263   ASSERT (get_date (&result, p, &now));
264   LOG (p, now, result);
265   ASSERT (result.tv_sec >= now.tv_sec
266           && result.tv_nsec == now.tv_nsec);
267
268   return 0;
269 }