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