A time interface class. This class replicates the normal time functions, but goes a couple of steps further. mbed library 82 and prior has a defective gmtime function. Also, this class enables access to setting the time, and adjusting the accuracy of the RTC.
Dependents: CI-data-logger-server WattEye X10Svr SSDP_Server
TimeInterface.cpp
00001 00002 #include "TimeInterface.h" 00003 00004 #include "rtc_api.h" 00005 00006 //#define DEBUG "Time" 00007 #include <cstdio> 00008 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00009 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00010 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00011 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00012 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00013 #else 00014 #define DBG(x, ...) 00015 #define WARN(x, ...) 00016 #define ERR(x, ...) 00017 #define INFO(x, ...) 00018 #endif 00019 00020 #ifdef WIN32 00021 // Fake it out for Win32 development and testing 00022 struct LPC { 00023 unsigned long CCR; // Clock Control register 00024 unsigned long GPREG0; // General Purpose Register #0 - 32-bit Battery backed 00025 unsigned long GPREG1; // General Purpose Register #1 - 32-bit Battery backed 00026 unsigned long CALIBRATION; // Calibration Register 00027 }; 00028 struct LPC X; 00029 struct LPC * LPC_RTC = &X; 00030 #define set_time(x) (void)x 00031 #endif 00032 00033 00034 TimeInterface::TimeInterface(EthernetInterface *net) 00035 { 00036 m_net = net; 00037 dst = false; 00038 memset(&dst_pair, 0, sizeof(dst_pair)); // that's enough to keep it from running 00039 } 00040 00041 TimeInterface::~TimeInterface() 00042 { 00043 } 00044 00045 NTPResult TimeInterface::setTime(const char* host, uint16_t port, uint32_t timeout) 00046 { 00047 NTPResult res; 00048 00049 if (m_net) { 00050 NTPClient ntp(m_net); 00051 // int16_t tzomin = get_tzo_min(); 00052 INFO("setTime(%s, %d, %d)\r\n", host, port, timeout); 00053 res = ntp.setTime(host, port, timeout); 00054 INFO(" ret: %d\r\n", res); 00055 if (res == NTP_OK) { 00056 // if the time was fetched successfully, then 00057 // let's save the time last set with the local tzo applied 00058 // and this saves the last time set for later precision 00059 // tuning. 00060 set_time(std::time(NULL)); 00061 } 00062 } else { 00063 ERR("No connection"); 00064 res = NTP_CONN; 00065 } 00066 return res; 00067 } 00068 00069 bool TimeInterface::parseDSTstring(TimeInterface::dst_event_t * result, const char * dstr) 00070 { 00071 int x; 00072 dst_event_t test_dst; 00073 00074 x = atoi(dstr); 00075 if (x >= 1 && x <= 12) { 00076 test_dst.MM = x; 00077 dstr = strchr(dstr, '/'); 00078 if (dstr++) { 00079 x = atoi(dstr); 00080 if (x >= 1 && x <= 31) { 00081 test_dst.DD = x; 00082 dstr = strchr(dstr, ','); 00083 if (dstr++) { 00084 x = atoi(dstr); 00085 if (x >= 0 && x <= 23) { 00086 test_dst.hh = x; 00087 dstr = strchr(dstr, ':'); 00088 if (dstr++) { 00089 x = atoi(dstr); 00090 if (x >= 0 && x <= 59) { 00091 test_dst.mm = x; 00092 memcpy(result, &test_dst, sizeof(dst_event_t)); 00093 INFO("parsed: %d/%d %d:%02d", test_dst.MM, test_dst.DD, test_dst.hh, test_dst.mm); 00094 return true; 00095 } 00096 } 00097 } 00098 } 00099 } 00100 } 00101 } 00102 return false; 00103 } 00104 00105 // parse MM/DD,hh:mm 00106 bool TimeInterface::set_dst(const char * dstStart, const char * dstStop) 00107 { 00108 dst_event_pair_t test_pair; 00109 00110 if (parseDSTstring(&test_pair.dst_start, dstStart) 00111 && parseDSTstring(&test_pair.dst_stop, dstStop)) { 00112 memcpy(&dst_pair, &test_pair, sizeof(dst_event_pair_t)); 00113 INFO("set_dst from (%s,%s)", dstStart, dstStop); 00114 return true; 00115 } 00116 WARN("failed to set_dst from (%s,%s)", dstStart, dstStop); 00117 return false; 00118 } 00119 00120 bool TimeInterface::set_dst(bool isdst) 00121 { 00122 dst = isdst; 00123 return true; 00124 } 00125 00126 bool TimeInterface::get_dst(void) 00127 { 00128 return dst; 00129 } 00130 00131 clock_t TimeInterface::clock(void) 00132 { 00133 return std::clock(); 00134 } 00135 00136 time_t TimeInterface::time(time_t * timer) 00137 { 00138 return std::time(timer); 00139 } 00140 00141 uint32_t TimeInterface::minutesSinceJan(int mon, int day, int hr, int min) 00142 { 00143 return (mon * 60 * 24 * 31) + (day * 60 * 24) + (hr * 60) + min; 00144 } 00145 00146 time_t TimeInterface::timelocal(time_t * timer) 00147 { 00148 time_t privTime; 00149 struct tm * tminfo; 00150 00151 if (dst_pair.dst_start.MM) { // may have to change the dst 00152 std::time(&privTime); 00153 tminfo = std::localtime(&privTime); 00154 00155 uint32_t min_since_jan = minutesSinceJan(tminfo->tm_mon + 1, tminfo->tm_mday, tminfo->tm_hour, tminfo->tm_min); 00156 uint32_t min_dst_start = minutesSinceJan(dst_pair.dst_start.MM, dst_pair.dst_start.DD, dst_pair.dst_start.hh, dst_pair.dst_start.mm) + get_tzo_min(); 00157 uint32_t min_dst_stop = minutesSinceJan(dst_pair.dst_stop.MM, dst_pair.dst_stop.DD, dst_pair.dst_stop.hh, dst_pair.dst_stop.mm) + get_tzo_min(); 00158 00159 if (min_since_jan >= min_dst_start && min_since_jan < min_dst_stop) { 00160 dst = 1; 00161 //INFO(" is dst: %u - %u - %u", min_since_jan, min_dst_start, min_dst_stop); 00162 } else { 00163 dst = 0; 00164 //INFO("not dst: %u - %u - %u", min_since_jan, min_dst_start, min_dst_stop); 00165 } 00166 } 00167 INFO(" timelocal: %u, %d, %d", std::time(timer), get_tzo_min(), dst); 00168 return std::time(timer) + get_tzo_min() * 60 + dst * 3600; 00169 } 00170 00171 char * TimeInterface::ctime(const time_t * timer) 00172 { 00173 char * p = std::ctime(timer); 00174 00175 if (strlen(p) < sizeof(result)) { 00176 strcpy(result, p); 00177 p = strchr(result, '\n'); 00178 if (p) 00179 *p = '\0'; 00180 } else { 00181 result[0] = '\0'; 00182 } 00183 return result; 00184 } 00185 00186 char * TimeInterface::asctime(const struct tm_ex * timeptr) 00187 { 00188 static const char wday_name[][4] = { 00189 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 00190 }; 00191 static const char mon_name[][4] = { 00192 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 00193 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 00194 }; 00195 struct tm_ex tmp = *timeptr; 00196 00197 tmp.tm_min += tmp.tm_tzo_min; 00198 while (tmp.tm_min >= 60) { 00199 tmp.tm_min -= 60; 00200 tmp.tm_hour++; 00201 } 00202 while (tmp.tm_min < 0) { 00203 tmp.tm_min += 60; 00204 tmp.tm_hour--; 00205 } 00206 while (tmp.tm_hour >= 24) { 00207 tmp.tm_wday = (tmp.tm_wday + 1) % 7; 00208 tmp.tm_mday++; 00209 tmp.tm_hour -= 24; 00210 } 00211 while (tmp.tm_hour < 0) { 00212 tmp.tm_wday = (tmp.tm_wday + 6) % 7; 00213 tmp.tm_mday--; 00214 tmp.tm_hour += 24; 00215 } 00216 sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d", 00217 wday_name[tmp.tm_wday % 7], 00218 mon_name[tmp.tm_mon % 12], 00219 tmp.tm_mday, tmp.tm_hour, 00220 tmp.tm_min, tmp.tm_sec, 00221 1900 + tmp.tm_year); 00222 return result; 00223 } 00224 00225 struct tm_ex * TimeInterface::localtime(const time_t * timer) 00226 { 00227 time_t priv = *timer + get_tzo_min() * 60 + dst * 3600; 00228 struct tm * tmp = std::localtime(&priv); 00229 00230 tm_ext.tm_sec = tmp->tm_sec; 00231 tm_ext.tm_min = tmp->tm_min; 00232 tm_ext.tm_hour = tmp->tm_hour; 00233 tm_ext.tm_mday = tmp->tm_mday; 00234 tm_ext.tm_mon = tmp->tm_mon; 00235 tm_ext.tm_year = tmp->tm_year; 00236 tm_ext.tm_wday = tmp->tm_wday; 00237 tm_ext.tm_yday = tmp->tm_yday; 00238 tm_ext.tm_isdst = tmp->tm_isdst; 00239 tm_ext.tm_tzo_min = get_tzo_min(); 00240 return &tm_ext; 00241 } 00242 00243 struct tm_ex * TimeInterface::gmtime(const time_t * timer) 00244 { 00245 struct tm * tmp = std::localtime(timer); 00246 00247 tm_ext.tm_sec = tmp->tm_sec; 00248 tm_ext.tm_min = tmp->tm_min; 00249 tm_ext.tm_hour = tmp->tm_hour; 00250 tm_ext.tm_mday = tmp->tm_mday; 00251 tm_ext.tm_mon = tmp->tm_mon; 00252 tm_ext.tm_year = tmp->tm_year; 00253 tm_ext.tm_wday = tmp->tm_wday; 00254 tm_ext.tm_yday = tmp->tm_yday; 00255 tm_ext.tm_isdst = tmp->tm_isdst; 00256 tm_ext.tm_tzo_min = get_tzo_min(); 00257 return &tm_ext; 00258 } 00259 00260 time_t TimeInterface::mktime(struct tm_ex * timeptr) 00261 { 00262 timeptr->tm_tzo_min = get_tzo_min(); 00263 return std::mktime((struct tm *)timeptr); 00264 } 00265 00266 size_t TimeInterface::strftime(char * ptr, size_t maxsize, const char * format, const struct tm_ex * timeptr) 00267 { 00268 return std::strftime(ptr, maxsize, format, (struct tm *)timeptr); 00269 } 00270 00271 double TimeInterface::difftime(time_t end, time_t beginning) 00272 { 00273 return std::difftime(end, beginning); 00274 } 00275 00276 00277 00278 // time zone functions 00279 00280 void TimeInterface::set_time(time_t t, int16_t tzo_min) 00281 { 00282 time_t tval = t - (tzo_min * 60); 00283 rtc_init(); 00284 rtc_write(tval); 00285 LPC_RTC->GPREG1 = tval; 00286 INFO("set_time(%s)", ctime(&tval)); 00287 } 00288 00289 void TimeInterface::set_tzo_min(int16_t tzo_min) 00290 { 00291 uint16_t th; 00292 uint32_t treg; 00293 00294 if (tzo_min >= -720 && tzo_min <= 720) { 00295 th = (uint16_t)(-tzo_min); 00296 treg = (th << 16) | (uint16_t)tzo_min; 00297 LPC_RTC->GPREG0 = treg; 00298 //printf("set_tzo(%d) %d is %08X\r\n", tzo, th, LPC_RTC->GPREG0); 00299 } 00300 } 00301 00302 int16_t TimeInterface::get_tzo_min(void) 00303 { 00304 uint16_t th, tl; 00305 00306 th = LPC_RTC->GPREG0 >> 16; 00307 tl = LPC_RTC->GPREG0; 00308 //printf("get_tzo() is %04X %04X\r\n", th, tl); 00309 if ((uint16_t)(th + tl) == 0) { 00310 return tl; 00311 } else { 00312 return 0; 00313 } 00314 } 00315 00316 time_t TimeInterface::get_timelastset(void) 00317 { 00318 return LPC_RTC->GPREG1; 00319 } 00320 00321 int32_t TimeInterface::get_cal() 00322 { 00323 int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF; 00324 00325 if (calvalue & 0x20000) { 00326 calvalue = -(calvalue & 0x1FFFF); 00327 } 00328 return calvalue; 00329 } 00330 00331 void TimeInterface::set_cal(int32_t calibration) 00332 { 00333 if (calibration) { 00334 if (calibration < 0) { 00335 calibration = (-calibration & 0x1FFFF) | 0x20000; 00336 } 00337 LPC_RTC->CCR = 0x000001; //(LPC_RTC->CCR & 0x0003); // Clear CCALEN to enable it 00338 } else { 00339 LPC_RTC->CCR = 0x000011; //(LPC_RTC->CCR & 0x0003) | 0x0010; // Set CCALEN to disable it 00340 } 00341 LPC_RTC->CALIBRATION = calibration; 00342 } 00343 00344 bool TimeInterface::adjust_sec(int32_t adjustSeconds) 00345 { 00346 time_t lastSet = get_timelastset(); 00347 00348 if (lastSet != 0) { 00349 time_t seconds = time(NULL); // get "now" according to the rtc 00350 int32_t delta = seconds - lastSet; 00351 //int32_t curCal = get_cal(); // calibration might want to leverage the current cal factor. 00352 int32_t calMAX = 131071; 00353 int32_t secPerDay = 86400; 00354 float errSecPerDay; 00355 00356 // Convert the current calibration and the adjustment into 00357 // the new calibration value 00358 // assume it is +10sec and it has been 2days, then the adjustment 00359 // needs to be +5 sec per day, or one adjustment every 1/5th 00360 // of a day, or 1 adjustment every 86400/5 counts. 00361 // delta = now - then (number of elapsed seconds) 00362 if (adjustSeconds != 0 && delta != 0) { 00363 int32_t calFactor; 00364 00365 // Make the clock correct 00366 seconds = seconds + adjustSeconds; 00367 set_time(seconds); 00368 // Compute the calibration factor 00369 errSecPerDay = (float)adjustSeconds / ((float)(delta)/secPerDay); 00370 calFactor = (int32_t)((float)secPerDay/errSecPerDay); 00371 if (abs(calFactor) < calMAX) 00372 set_cal(calFactor); 00373 } 00374 return true; 00375 } else { 00376 return false; 00377 } 00378 } 00379 00380 00381 // ############################################################################# 00382 /* 00383 * Enhancement to use a custom tm_ex struct and the time zone by D. Smart 00384 * %Z 00385 * 00386 * Copyright (c) 1994 Powerdog Industries. All rights reserved. 00387 * 00388 * Redistribution and use in source and binary forms, without 00389 * modification, are permitted provided that the following conditions 00390 * are met: 00391 * 1. Redistributions of source code must retain the above copyright 00392 * notice, this list of conditions and the following disclaimer. 00393 * 2. Redistributions in binary form must reproduce the above copyright 00394 * notice, this list of conditions and the following disclaimer 00395 * in the documentation and/or other materials provided with the 00396 * distribution. 00397 * 3. All advertising materials mentioning features or use of this 00398 * software must display the following acknowledgement: 00399 * This product includes software developed by Powerdog Industries. 00400 * 4. The name of Powerdog Industries may not be used to endorse or 00401 * promote products derived from this software without specific prior 00402 * written permission. 00403 * 00404 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY 00405 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00406 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00407 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE 00408 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00409 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00410 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 00411 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00412 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 00413 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 00414 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00415 */ 00416 00417 #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) 00418 00419 struct dtconv { 00420 char *abbrev_month_names[12]; 00421 char *month_names[12]; 00422 char *abbrev_weekday_names[7]; 00423 char *weekday_names[7]; 00424 char *time_format; 00425 char *sdate_format; 00426 char *dtime_format; 00427 char *am_string; 00428 char *pm_string; 00429 char *ldate_format; 00430 char *zone_names[10]; 00431 int8_t zone_offsets[10]; 00432 }; 00433 00434 static const struct dtconv En_US = { 00435 { 00436 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 00437 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 00438 }, 00439 { 00440 "January", "February", "March", "April", 00441 "May", "June", "July", "August", 00442 "September", "October", "November", "December" 00443 }, 00444 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }, 00445 { 00446 "Sunday", "Monday", "Tuesday", "Wednesday", 00447 "Thursday", "Friday", "Saturday" 00448 }, 00449 "%H:%M:%S", 00450 "%m/%d/%y", 00451 "%a %b %e %T %Z %Y", 00452 "AM", 00453 "PM", 00454 "%A, %B, %e, %Y", 00455 { "UTC", "EST", "CST", "MST", "PST", "YST", "CAT", "HST", "CET", "EET", }, 00456 { 0, -5, -6, -7, -8, -9, -10, -10, +1, +2, }, 00457 }; 00458 00459 00460 #ifndef isprint 00461 #define in_range(c, lo, up) ((uint8_t)c >= lo && (uint8_t)c <= up) 00462 #define isprint(c) in_range(c, 0x20, 0x7f) 00463 #define isdigit(c) in_range(c, '0', '9') 00464 #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) 00465 #define islower(c) in_range(c, 'a', 'z') 00466 #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') 00467 #endif 00468 00469 00470 const char * TimeInterface::strptime(const char *buf, char *fmt, struct tm_ex *tm) 00471 { 00472 char c, *ptr; 00473 int i, len; 00474 bool fSet_wday = false; // so we can notice if the wday was set 00475 00476 ptr = fmt; 00477 while (*ptr != 0) { 00478 if (*buf == 0) 00479 break; 00480 00481 c = *ptr++; 00482 00483 if (c != '%') { 00484 if (isspace(c)) 00485 while (*buf != 0 && isspace(*buf)) 00486 buf++; 00487 else if (c != *buf++) 00488 return 0; 00489 continue; 00490 } 00491 00492 c = *ptr++; 00493 switch (c) { 00494 case 0: 00495 case '%': 00496 if (*buf++ != '%') 00497 return 0; 00498 break; 00499 00500 case 'C': 00501 buf = strptime(buf, En_US.ldate_format, tm); 00502 if (buf == 0) 00503 return 0; 00504 break; 00505 00506 case 'c': 00507 buf = strptime(buf, "%x %X", tm); 00508 if (buf == 0) 00509 return 0; 00510 break; 00511 00512 case 'D': 00513 buf = strptime(buf, "%m/%d/%y", tm); 00514 if (buf == 0) 00515 return 0; 00516 break; 00517 00518 case 'R': 00519 buf = strptime(buf, "%H:%M", tm); 00520 if (buf == 0) 00521 return 0; 00522 break; 00523 00524 case 'r': 00525 buf = strptime(buf, "%I:%M:%S %p", tm); 00526 if (buf == 0) 00527 return 0; 00528 break; 00529 00530 case 'T': 00531 buf = strptime(buf, "%H:%M:%S", tm); 00532 if (buf == 0) 00533 return 0; 00534 break; 00535 00536 case 'X': 00537 buf = strptime(buf, En_US.time_format, tm); 00538 if (buf == 0) 00539 return 0; 00540 break; 00541 00542 case 'x': 00543 buf = strptime(buf, En_US.sdate_format, tm); 00544 if (buf == 0) 00545 return 0; 00546 break; 00547 00548 case 'j': 00549 if (!isdigit(*buf)) 00550 return 0; 00551 00552 for (i = 0; *buf != 0 && isdigit(*buf); buf++) { 00553 i *= 10; 00554 i += *buf - '0'; 00555 } 00556 if (i > 365) 00557 return 0; 00558 00559 tm->tm_yday = i; 00560 break; 00561 00562 case 'M': 00563 case 'S': 00564 if (*buf == 0 || isspace(*buf)) 00565 break; 00566 00567 if (!isdigit(*buf)) 00568 return 0; 00569 00570 for (i = 0; *buf != 0 && isdigit(*buf); buf++) { 00571 i *= 10; 00572 i += *buf - '0'; 00573 } 00574 if (i > 59) 00575 return 0; 00576 00577 if (c == 'M') 00578 tm->tm_min = i; 00579 else 00580 tm->tm_sec = i; 00581 00582 if (*buf != 0 && isspace(*buf)) 00583 while (*ptr != 0 && !isspace(*ptr)) 00584 ptr++; 00585 break; 00586 00587 case 'H': 00588 case 'I': 00589 case 'k': 00590 case 'l': 00591 if (!isdigit(*buf)) 00592 return 0; 00593 00594 for (i = 0; *buf != 0 && isdigit(*buf); buf++) { 00595 i *= 10; 00596 i += *buf - '0'; 00597 } 00598 if (c == 'H' || c == 'k') { 00599 if (i > 23) 00600 return 0; 00601 } else if (i > 11) 00602 return 0; 00603 00604 tm->tm_hour = i; 00605 00606 if (*buf != 0 && isspace(*buf)) 00607 while (*ptr != 0 && !isspace(*ptr)) 00608 ptr++; 00609 break; 00610 00611 case 'p': 00612 len = strlen(En_US.am_string); 00613 if (strncasecmp(buf, En_US.am_string, len) == 0) { 00614 if (tm->tm_hour > 12) 00615 return 0; 00616 if (tm->tm_hour == 12) 00617 tm->tm_hour = 0; 00618 buf += len; 00619 break; 00620 } 00621 00622 len = strlen(En_US.pm_string); 00623 if (strncasecmp(buf, En_US.pm_string, len) == 0) { 00624 if (tm->tm_hour > 12) 00625 return 0; 00626 if (tm->tm_hour != 12) 00627 tm->tm_hour += 12; 00628 buf += len; 00629 break; 00630 } 00631 00632 return 0; 00633 00634 case 'A': 00635 case 'a': 00636 for (i = 0; i < asizeof(En_US.weekday_names); i++) { 00637 len = strlen(En_US.weekday_names[i]); 00638 if (strncasecmp(buf, 00639 En_US.weekday_names[i], 00640 len) == 0) 00641 break; 00642 00643 len = strlen(En_US.abbrev_weekday_names[i]); 00644 if (strncasecmp(buf, 00645 En_US.abbrev_weekday_names[i], 00646 len) == 0) 00647 break; 00648 } 00649 if (i == asizeof(En_US.weekday_names)) 00650 return 0; 00651 fSet_wday = true; 00652 tm->tm_wday = i; 00653 buf += len; 00654 break; 00655 00656 case 'd': 00657 case 'e': 00658 if (!isdigit(*buf)) 00659 return 0; 00660 00661 for (i = 0; *buf != 0 && isdigit(*buf); buf++) { 00662 i *= 10; 00663 i += *buf - '0'; 00664 } 00665 if (i > 31) 00666 return 0; 00667 00668 tm->tm_mday = i; 00669 00670 if (*buf != 0 && isspace(*buf)) 00671 while (*ptr != 0 && !isspace(*ptr)) 00672 ptr++; 00673 break; 00674 00675 case 'B': 00676 case 'b': 00677 case 'h': 00678 for (i = 0; i < asizeof(En_US.month_names); i++) { 00679 len = strlen(En_US.month_names[i]); 00680 if (strncasecmp(buf, 00681 En_US.month_names[i], 00682 len) == 0) 00683 break; 00684 00685 len = strlen(En_US.abbrev_month_names[i]); 00686 if (strncasecmp(buf, 00687 En_US.abbrev_month_names[i], 00688 len) == 0) 00689 break; 00690 } 00691 if (i == asizeof(En_US.month_names)) 00692 return 0; 00693 00694 tm->tm_mon = i; 00695 buf += len; 00696 break; 00697 00698 case 'm': 00699 if (!isdigit(*buf)) 00700 return 0; 00701 00702 for (i = 0; *buf != 0 && isdigit(*buf); buf++) { 00703 i *= 10; 00704 i += *buf - '0'; 00705 } 00706 if (i < 1 || i > 12) 00707 return 0; 00708 00709 tm->tm_mon = i - 1; 00710 00711 if (*buf != 0 && isspace(*buf)) 00712 while (*ptr != 0 && !isspace(*ptr)) 00713 ptr++; 00714 break; 00715 00716 case 'Y': 00717 case 'y': 00718 if (*buf == 0 || isspace(*buf)) 00719 break; 00720 00721 if (!isdigit(*buf)) 00722 return 0; 00723 00724 for (i = 0; *buf != 0 && isdigit(*buf); buf++) { 00725 i *= 10; 00726 i += *buf - '0'; 00727 } 00728 if (c == 'Y') 00729 i -= 1900; 00730 if (i < 0) 00731 return 0; 00732 00733 tm->tm_year = i; 00734 00735 if (*buf != 0 && isspace(*buf)) 00736 while (*ptr != 0 && !isspace(*ptr)) 00737 ptr++; 00738 break; 00739 case 'Z': 00740 for (i = 0; i < asizeof(En_US.zone_names); i++) { 00741 len = strlen(En_US.zone_names[i]); 00742 if (strncasecmp(buf, 00743 En_US.zone_names[i], 00744 len) == 0) 00745 break; 00746 } 00747 if (i == asizeof(En_US.zone_names)) 00748 return 0; 00749 tm->tm_tzo_min = En_US.zone_offsets[i] * 60; 00750 buf += len; 00751 break; 00752 } 00753 } 00754 if (!fSet_wday) { 00755 if (mktime(tm) == (time_t)-1) 00756 tm->tm_wday = 7; 00757 } 00758 return buf; 00759 }
Generated on Tue Jul 12 2022 16:41:47 by 1.7.2