1 #include "config.h"
2 #include "ntp_calendar.h"
3
4 #include <stdlib.h>
5 #include <errno.h>
6
7 #include "ntp_types.h"
8 #include "ntp_fp.h"
9 #include "vint64ops.h"
10
11 /*
12 * If we're called with 1 arg, it's a u_long timestamp.
13 * If we're called with 3 args, we're expecting YYYY MM DD,
14 * and MM must be 6 or 12, and DD must be 28,
15 * If we're called with 2 args, we're expecting YYYY MM, and
16 * MM mst be 6 or 12, and we assume DD is 28.
17 */
18
19 char *progname;
20 static const char *MONTHS[] =
21 { "January", "February", "March", "April", "May", "June",
22 "July", "August", "September", "October", "November",
23 "December" };
24
25 void usage(void);
26
27 void
usage(void)28 usage(void)
29 {
30 printf("Usage:\n");
31 printf(" %s nnnnnn\n", progname);
32 printf(" %s YYYY [6|12]\n", progname);
33 printf(" %s YYYY [6|12] 28\n", progname);
34
35 return;
36 }
37
38
39 int
main(int argc,char ** argv)40 main(
41 int argc, /* command line options */
42 char **argv /* poiniter to list of tokens */
43 )
44 {
45 int err = 0;
46 vint64 expires;
47 unsigned int year = 0;
48 unsigned int mon = 0;
49 unsigned int dom = 0;
50 int scount;
51 char *ep;
52 struct calendar cal = {0};
53
54 progname = argv[0];
55
56 switch(argc) {
57 case 2: /* 1 arg, must be a string of digits */
58 expires = strtouv64(argv[1], &ep, 10);
59
60 if (0 == *ep) {
61 ntpcal_ntp64_to_date(&cal, &expires);
62
63 printf("%02u %s %04u %02u:%02u:%02u\n"
64 , cal.monthday
65 , MONTHS[cal.month - 1]
66 , cal.year
67 , cal.hour
68 , cal.minute
69 , cal.second
70 );
71
72 exit(0);
73 } else {
74 printf("1 arg, but not a string of digits: <%s>\n",
75 argv[1]);
76 err = 1;
77 }
78 break;
79 ;;
80 case 3: /* 2 args, must be YY MM, where MM is 6 or 12 */
81 dom = 28;
82 scount = sscanf(argv[1], "%u", &year);
83 if (1 == scount) {
84 // printf("2 args: year %u\n", year);
85 } else {
86 printf("2 args, but #1 is not a string of digits: <%s>\n", argv[1]);
87 err = 1;
88 }
89
90 scount = sscanf(argv[2], "%u", &mon);
91 if (1 == scount) {
92 if (6 == mon || 12 == mon) {
93 // printf("2 args: month %u\n", mon);
94 } else {
95 printf("2 arg, but #2 is not 6 or 12: <%d>\n", mon);
96 err = 1;
97 }
98 } else {
99 printf("2 arg, but #2 is not a string of digits: <%s>\n", argv[2]);
100 err = 1;
101 }
102
103 break;
104 ;;
105 case 4: /* 3 args, YY MM DD, where MM is 6 or 12, DD is 28 */
106 scount = sscanf(argv[1], "%u", &year);
107 if (1 == scount) {
108 // printf("3 args: year %u\n", year);
109 } else {
110 printf("3 args, but #1 is not a string of digits: <%s>\n", argv[1]);
111 err = 1;
112 }
113
114 scount = sscanf(argv[2], "%u", &mon);
115 if (1 == scount) {
116 if (6 == mon || 12 == mon) {
117 // printf("3 args: month %u\n", mon);
118 } else {
119 printf("3 arg, but #2 is not 6 or 12: <%d>\n", mon);
120 err = 1;
121 }
122 } else {
123 printf("3 arg, but #2 is not a string of digits: <%s>\n", argv[2]);
124 err = 1;
125 }
126
127 scount = sscanf(argv[3], "%u", &dom);
128 if (1 == scount) {
129 if (28 == dom) {
130 // printf("3 args: dom %u\n", dom);
131 } else {
132 printf("3 arg, but #3 is not 28: <%d>\n", dom);
133 err = 1;
134 }
135 } else {
136 printf("3 arg, but #3 is not a string of digits: <%s>\n", argv[2]);
137 err = 1;
138 }
139
140 break;
141 ;;
142 default:
143 err = 1;
144 break;
145 ;;
146 }
147
148 if (err) {
149 usage();
150 exit(err);
151 }
152
153 cal.year = year;
154 cal.month = mon;
155 cal.monthday = dom;
156 cal.hour = 0;
157 cal.minute = 0;
158 cal.second = 0;
159
160 printf("%u ", ntpcal_date_to_ntp(&cal));
161
162 printf("%02d %s %04d "
163 , cal.monthday
164 , MONTHS[cal.month - 1]
165 , cal.year
166 );
167 printf("\n");
168
169 exit(err);
170 }
171
172 #if 0
173
174
175 void
176 test_DateGivenMonthDay(void) {
177 // 2010-06-24 12:50:00
178 struct calendar input = {2010, 0, 6, 24, 12, 50, 0};
179
180 u_long expected = 3486372600UL; // This is the timestamp above.
181
182 TEST_ASSERT_EQUAL_UINT(expected, caltontp(&input));
183 }
184
185 void
186 test_DateGivenYearDay(void) {
187 // 2010-06-24 12:50:00
188 // This is the 175th day of 2010.
189 struct calendar input = {2010, 175, 0, 0, 12, 50, 0};
190
191 u_long expected = 3486372600UL; // This is the timestamp above.
192
193 TEST_ASSERT_EQUAL_UINT(expected, caltontp(&input));
194 }
195
196 void
197 test_DateLeapYear(void) {
198 // 2012-06-24 12:00:00
199 // This is the 176th day of 2012 (since 2012 is a leap year).
200 struct calendar inputYd = {2012, 176, 0, 0, 12, 00, 00};
201 struct calendar inputMd = {2012, 0, 6, 24, 12, 00, 00};
202
203 u_long expected = 3549528000UL;
204
205 TEST_ASSERT_EQUAL_UINT(expected, caltontp(&inputYd));
206 TEST_ASSERT_EQUAL_UINT(expected, caltontp(&inputMd));
207 }
208
209 void
210 test_WraparoundDateIn2036(void) {
211 // 2036-02-07 06:28:16
212 // This is (one) wrapping boundary where we go from ULONG_MAX to 0.
213 struct calendar input = {2036, 0, 2, 7, 6, 28, 16};
214
215 u_long expected = 0UL;
216
217 TEST_ASSERT_EQUAL_UINT(expected, caltontp(&input));
218 }
219
220 #endif
221