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 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 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