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