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