• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <limits.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5 #include "test.h"
6 
7 static char buffer[100];
8 
checkStrftime(const char * format,const struct tm * tm,const char * expected)9 static void checkStrftime(const char* format, const struct tm* tm,
10 		const char* expected) {
11 	size_t resultLength = strftime(buffer, sizeof(buffer), format, tm);
12 
13 	if (resultLength != 0 && strcmp(buffer, expected) != 0) {
14 		t_error("\"%s\": expected \"%s\", got \"%s\"\n", format, expected, buffer);
15 	} else if (resultLength == 0 && strlen(expected) != 0) {
16 		t_error("\"%s\": expected \"%s\", got nothing\n", format, expected);
17 	}
18 }
19 
20 static struct tm tm1 = {
21 	.tm_sec = 45,
22 	.tm_min = 23,
23 	.tm_hour = 13,
24 	.tm_mday = 3,
25 	.tm_mon = 0,
26 	.tm_year = 2016 - 1900,
27 	.tm_wday = 0,
28 	.tm_yday = 2,
29 	.tm_isdst = 0
30 };
31 
32 static struct tm tm2 = {
33 	.tm_sec = 53,
34 	.tm_min = 17,
35 	.tm_hour = 5,
36 	.tm_mday = 5,
37 	.tm_mon = 0,
38 	.tm_year = 10009 - 1900,
39 	.tm_wday = 1,
40 	.tm_yday = 4,
41 	.tm_isdst = 0
42 };
43 
44 static struct tm tm3 = {
45 	.tm_sec = 0,
46 	.tm_min = 0,
47 	.tm_hour = 12,
48 	.tm_mday = 23,
49 	.tm_mon = 1,
50 	.tm_year = 0 - 1900,
51 	.tm_wday = 3,
52 	.tm_yday = 53,
53 	.tm_isdst = 0
54 };
55 
56 static struct tm tm4 = {
57 	.tm_sec = 0,
58 	.tm_min = 0,
59 	.tm_hour = 0,
60 	.tm_mday = 1,
61 	.tm_mon = 0,
62 	.tm_year = -123 - 1900,
63 	.tm_wday = 1,
64 	.tm_yday = 0,
65 	.tm_isdst = 0
66 };
67 
68 static struct tm tm5 = {
69 	.tm_sec = 0,
70 	.tm_min = 0,
71 	.tm_hour = 0,
72 	.tm_mday = 1,
73 	.tm_mon = 0,
74 	.tm_year = INT_MAX,
75 	.tm_wday = 3,
76 	.tm_yday = 0,
77 	.tm_isdst = 0
78 };
79 
main()80 int main() {
81 	setenv("TZ", "UTC0", 1);
82 
83 	checkStrftime("%c", &tm1, "Sun Jan  3 13:23:45 2016");
84 	checkStrftime("%c", &tm2, "Mon Jan  5 05:17:53 +10009");
85 	checkStrftime("%c", &tm3, "Wed Feb 23 12:00:00 0000");
86 
87 	// The POSIX.1-2008 standard does not specify the padding character for
88 	// "%C". The C standard requires that the number is padded by '0'.
89 	// See also http://austingroupbugs.net/view.php?id=1184
90 	checkStrftime("%C", &tm1, "20");
91 	checkStrftime("%03C", &tm1, "020");
92 	checkStrftime("%+3C", &tm1, "+20");
93 	checkStrftime("%C", &tm2, "100");
94 	checkStrftime("%C", &tm3, "00");
95 	checkStrftime("%01C", &tm3, "0");
96 
97 	checkStrftime("%F", &tm1, "2016-01-03");
98 	checkStrftime("%012F", &tm1, "002016-01-03");
99 	checkStrftime("%+10F", &tm1, "2016-01-03");
100 	checkStrftime("%+11F", &tm1, "+2016-01-03");
101 	checkStrftime("%F", &tm2, "+10009-01-05");
102 	checkStrftime("%011F", &tm2, "10009-01-05");
103 	checkStrftime("%F", &tm3, "0000-02-23");
104 	checkStrftime("%01F", &tm3, "0-02-23");
105 	checkStrftime("%06F", &tm3, "0-02-23");
106 	checkStrftime("%010F", &tm3, "0000-02-23");
107 	checkStrftime("%F", &tm4, "-123-01-01");
108 	checkStrftime("%011F", &tm4, "-0123-01-01");
109 
110 	checkStrftime("%g", &tm1, "15");
111 	checkStrftime("%g", &tm2, "09");
112 
113 	checkStrftime("%G", &tm1, "2015");
114 	checkStrftime("%+5G", &tm1, "+2015");
115 	checkStrftime("%04G", &tm2, "10009");
116 
117 	checkStrftime("%r", &tm1, "01:23:45 PM");
118 	checkStrftime("%r", &tm2, "05:17:53 AM");
119 	checkStrftime("%r", &tm3, "12:00:00 PM");
120 	checkStrftime("%r", &tm4, "12:00:00 AM");
121 
122 	// The "%s" specifier was accepted by the Austin Group for the next POSIX.1
123 	// revision. See http://austingroupbugs.net/view.php?id=169
124 	checkStrftime("%s", &tm1, "1451827425");
125 	if (sizeof(time_t) * CHAR_BIT >= 64) {
126 		checkStrftime("%s", &tm2, "253686748673");
127 	}
128 
129 	checkStrftime("%T", &tm1, "13:23:45");
130 	checkStrftime("%T", &tm2, "05:17:53");
131 	checkStrftime("%T", &tm3, "12:00:00");
132 	checkStrftime("%T", &tm4, "00:00:00");
133 
134 	checkStrftime("%U", &tm1, "01");
135 	checkStrftime("%U", &tm2, "01");
136 	checkStrftime("%U", &tm3, "08");
137 
138 	checkStrftime("%V", &tm1, "53");
139 	checkStrftime("%V", &tm2, "02");
140 	checkStrftime("%V", &tm3, "08");
141 
142 	checkStrftime("%W", &tm1, "00");
143 	checkStrftime("%W", &tm2, "01");
144 	checkStrftime("%W", &tm3, "08");
145 
146 	checkStrftime("%x", &tm1, "01/03/16");
147 	checkStrftime("%X", &tm1, "13:23:45");
148 	checkStrftime("%y", &tm1, "16");
149 
150 	// There is no standard that explicitly specifies the exact format of "%Y".
151 	// The C standard says that "%F" is equivalent to "%Y-%m-%d". The
152 	// POSIX.1-2008 standard says that "%F" is equivalent to "%+4Y-%m-%d".
153 	// This implies that to conform to both standards "%Y" needs to be
154 	// equivalent to "%+4Y".
155 	// See also http://austingroupbugs.net/view.php?id=739
156 	checkStrftime("%Y", &tm1, "2016");
157 	checkStrftime("%05Y", &tm1, "02016");
158 	checkStrftime("%+4Y", &tm1, "2016");
159 	checkStrftime("%+5Y", &tm1, "+2016");
160 	checkStrftime("%Y", &tm2, "+10009");
161 	checkStrftime("%05Y", &tm2, "10009");
162 	checkStrftime("%Y", &tm3, "0000");
163 	checkStrftime("%02Y", &tm3, "00");
164 	checkStrftime("%+5Y", &tm3, "+0000");
165 	checkStrftime("%Y", &tm4, "-123");
166 	checkStrftime("%+4Y", &tm4, "-123");
167 	checkStrftime("%+5Y", &tm4, "-0123");
168 
169 	if (INT_MAX == 0x7FFFFFFF) {
170 		// The standard does not specify any range for tm_year, so INT_MAX
171 		// should be valid.
172 		checkStrftime("%y", &tm5, "47");
173 		checkStrftime("%Y", &tm5, "+2147485547");
174 		checkStrftime("%011Y", &tm5, "02147485547");
175 		if (sizeof(time_t) * CHAR_BIT >= 64) {
176 			checkStrftime("%s", &tm5, "67768036160140800");
177 		}
178 	}
179 
180 	return t_status;
181 }
182