1 | /* Test for strptime. |
2 | Copyright (C) 1998-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <locale.h> |
20 | #include <stdio.h> |
21 | #include <stdlib.h> |
22 | #include <string.h> |
23 | #include <time.h> |
24 | |
25 | |
26 | static const struct |
27 | { |
28 | const char *locale; |
29 | const char *input; |
30 | const char *format; |
31 | int wday; |
32 | int yday; |
33 | int mon; |
34 | int mday; |
35 | } day_tests[] = |
36 | { |
37 | { "C" , "2000-01-01" , "%Y-%m-%d" , 6, 0, 0, 1 }, |
38 | { "C" , "03/03/00" , "%D" , 5, 62, 2, 3 }, |
39 | { "C" , "9/9/99" , "%x" , 4, 251, 8, 9 }, |
40 | { "C" , "19990502123412" , "%Y%m%d%H%M%S" , 0, 121, 4, 2 }, |
41 | { "C" , "2001 20 Mon" , "%Y %U %a" , 1, 140, 4, 21 }, |
42 | { "C" , "2001 21 Mon" , "%Y %W %a" , 1, 140, 4, 21 }, |
43 | { "C" , "2001 21 Mon" , "%2000Y %W %a" , 1, 140, 4, 21 }, |
44 | { "C" , "2001 21 Mon" , "%^Y %W %a" , 1, 140, 4, 21 }, |
45 | { "C" , "2001 EST 21 Mon" , "%Y %Z %W %a" , 1, 140, 4, 21 }, |
46 | { "C" , "2012 00 Sun" , "%Y %W %a" , 0, 0, 0, 1 }, |
47 | { "ja_JP.EUC-JP" , "2000-01-01 08:12:21 AM" , "%Y-%m-%d %I:%M:%S %p" , |
48 | 6, 0, 0, 1 }, |
49 | { "en_US.ISO-8859-1" , "2000-01-01 08:12:21 PM" , "%Y-%m-%d %I:%M:%S %p" , |
50 | 6, 0, 0, 1 }, |
51 | { "ja_JP.EUC-JP" , "2001 20 \xb7\xee" , "%Y %U %a" , 1, 140, 4, 21 }, |
52 | { "ja_JP.EUC-JP" , "2001 21 \xb7\xee" , "%Y %W %a" , 1, 140, 4, 21 }, |
53 | /* Most of the languages do not need the declension of the month names |
54 | and do not distinguish between %B and %OB. */ |
55 | { "en_US.ISO-8859-1" , "November 17, 2017" , "%B %e, %Y" , 5, 320, 10, 17 }, |
56 | { "de_DE.ISO-8859-1" , "18. Nov 2017" , "%d. %b %Y" , 6, 321, 10, 18 }, |
57 | { "fr_FR.UTF-8" , "19 novembre 2017" , "%d %OB %Y" , 0, 322, 10, 19 }, |
58 | { "es_ES.UTF-8" , "20 de nov de 2017" , "%d de %Ob de %Y" , 1, 323, 10, 20 }, |
59 | /* Some languages do need the declension of the month names. */ |
60 | { "pl_PL.UTF-8" , "21 lis 2017" , "%d %b %Y" , 2, 324, 10, 21 }, |
61 | { "pl_PL.UTF-8" , "22 LIS 2017" , "%d %B %Y" , 3, 325, 10, 22 }, |
62 | { "pl_PL.UTF-8" , "23 listopada 2017" , "%d %B %Y" , 4, 326, 10, 23 }, |
63 | /* The nominative case is incorrect here but it is parseable. */ |
64 | { "pl_PL.UTF-8" , "24 listopad 2017" , "%d %OB %Y" , 5, 327, 10, 24 }, |
65 | { "pl_PL.UTF-8" , "25 lis 2017" , "%d %Ob %Y" , 6, 328, 10, 25 }, |
66 | /* ноя - pronounce: 'noya' - "Nov" (abbreviated "November") in Russian. */ |
67 | { "ru_RU.UTF-8" , "26 ноя 2017" , "%d %b %Y" , 0, 329, 10, 26 }, |
68 | /* мая - pronounce: 'maya' - "of May" (the genitive case, both full and |
69 | abbreviated) in Russian. */ |
70 | { "ru_RU.UTF-8" , "19 мая 2018" , "%d %b %Y" , 6, 138, 4, 19 }, |
71 | /* май - pronounce: 'may' - "May" (the nominative case, both full and |
72 | abbreviated) in Russian. |
73 | The nominative case is incorrect here but it is parseable. */ |
74 | { "ru_RU.UTF-8" , "20 май 2018" , "%d %Ob %Y" , 0, 139, 4, 20 }, |
75 | }; |
76 | |
77 | |
78 | static const struct |
79 | { |
80 | const char *input; |
81 | const char *format; |
82 | const char *output; |
83 | int wday; |
84 | int yday; |
85 | } tm_tests [] = |
86 | { |
87 | {"17410105012000" , "%H%M%S%d%m%Y" , "2000-01-05 17:41:01" , 3, 4} |
88 | }; |
89 | |
90 | |
91 | |
92 | static int |
93 | test_tm (void) |
94 | { |
95 | struct tm tm; |
96 | size_t i; |
97 | int result = 0; |
98 | char buf[100]; |
99 | |
100 | for (i = 0; i < sizeof (tm_tests) / sizeof (tm_tests[0]); ++i) |
101 | { |
102 | memset (&tm, '\0', sizeof (tm)); |
103 | |
104 | char *ret = strptime (tm_tests[i].input, tm_tests[i].format, &tm); |
105 | if (ret == NULL) |
106 | { |
107 | printf (format: "strptime returned NULL for `%s'\n" , tm_tests[i].input); |
108 | result = 1; |
109 | continue; |
110 | } |
111 | else if (*ret != '\0') |
112 | { |
113 | printf (format: "not all of `%s' read\n" , tm_tests[i].input); |
114 | result = 1; |
115 | } |
116 | strftime (buf, sizeof (buf), "%F %T" , &tm); |
117 | printf (format: "strptime (\"%s\", \"%s\", ...)\n" |
118 | "\tshould be: %s, wday = %d, yday = %3d\n" |
119 | "\t is: %s, wday = %d, yday = %3d\n" , |
120 | tm_tests[i].input, tm_tests[i].format, |
121 | tm_tests[i].output, |
122 | tm_tests[i].wday, tm_tests[i].yday, |
123 | buf, tm.tm_wday, tm.tm_yday); |
124 | |
125 | if (strcmp (buf, tm_tests[i].output) != 0) |
126 | { |
127 | printf (format: "Time and date are not correct.\n" ); |
128 | result = 1; |
129 | } |
130 | if (tm.tm_wday != tm_tests[i].wday) |
131 | { |
132 | printf (format: "weekday for `%s' incorrect: %d instead of %d\n" , |
133 | tm_tests[i].input, tm.tm_wday, tm_tests[i].wday); |
134 | result = 1; |
135 | } |
136 | if (tm.tm_yday != tm_tests[i].yday) |
137 | { |
138 | printf (format: "yearday for `%s' incorrect: %d instead of %d\n" , |
139 | tm_tests[i].input, tm.tm_yday, tm_tests[i].yday); |
140 | result = 1; |
141 | } |
142 | } |
143 | |
144 | return result; |
145 | } |
146 | |
147 | |
148 | static int |
149 | do_test (void) |
150 | { |
151 | struct tm tm; |
152 | size_t i; |
153 | int result = 0; |
154 | |
155 | for (i = 0; i < sizeof (day_tests) / sizeof (day_tests[0]); ++i) |
156 | { |
157 | memset (&tm, '\0', sizeof (tm)); |
158 | |
159 | if (setlocale (LC_ALL, day_tests[i].locale) == NULL) |
160 | { |
161 | printf (format: "cannot set locale %s: %m\n" , day_tests[i].locale); |
162 | exit (EXIT_FAILURE); |
163 | } |
164 | |
165 | char *ret = strptime (day_tests[i].input, day_tests[i].format, &tm); |
166 | if (ret == NULL) |
167 | { |
168 | printf (format: "strptime returned NULL for `%s'\n" , day_tests[i].input); |
169 | result = 1; |
170 | continue; |
171 | } |
172 | else if (*ret != '\0') |
173 | { |
174 | printf (format: "not all of `%s' read\n" , day_tests[i].input); |
175 | result = 1; |
176 | } |
177 | |
178 | printf (format: "strptime (\"%s\", \"%s\", ...)\n" |
179 | "\tshould be: wday = %d, yday = %3d, mon = %2d, mday = %2d\n" |
180 | "\t is: wday = %d, yday = %3d, mon = %2d, mday = %2d\n" , |
181 | day_tests[i].input, day_tests[i].format, |
182 | day_tests[i].wday, day_tests[i].yday, |
183 | day_tests[i].mon, day_tests[i].mday, |
184 | tm.tm_wday, tm.tm_yday, tm.tm_mon, tm.tm_mday); |
185 | |
186 | if (tm.tm_wday != day_tests[i].wday) |
187 | { |
188 | printf (format: "weekday for `%s' incorrect: %d instead of %d\n" , |
189 | day_tests[i].input, tm.tm_wday, day_tests[i].wday); |
190 | result = 1; |
191 | } |
192 | if (tm.tm_yday != day_tests[i].yday) |
193 | { |
194 | printf (format: "yearday for `%s' incorrect: %d instead of %d\n" , |
195 | day_tests[i].input, tm.tm_yday, day_tests[i].yday); |
196 | result = 1; |
197 | } |
198 | if (tm.tm_mon != day_tests[i].mon) |
199 | { |
200 | printf (format: "month for `%s' incorrect: %d instead of %d\n" , |
201 | day_tests[i].input, tm.tm_mon, day_tests[i].mon); |
202 | result = 1; |
203 | } |
204 | if (tm.tm_mday != day_tests[i].mday) |
205 | { |
206 | printf (format: "monthday for `%s' incorrect: %d instead of %d\n" , |
207 | day_tests[i].input, tm.tm_mday, day_tests[i].mday); |
208 | result = 1; |
209 | } |
210 | } |
211 | |
212 | setlocale (LC_ALL, "C" ); |
213 | |
214 | result |= test_tm (); |
215 | |
216 | return result; |
217 | } |
218 | |
219 | #define TEST_FUNCTION do_test () |
220 | #include "../test-skeleton.c" |
221 | |