Changeset c2b0e10 in mainline for uspace/lib/posix/time.c
- Timestamp:
- 2012-04-23T21:42:27Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5b3394c
- Parents:
- cb948777
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/time.c
rcb948777 rc2b0e10 192 192 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) + 193 193 _day_of_year(year, mon, mday); 194 }195 196 /**197 * Seconds since the Epoch. see also _days_since_epoch().198 *199 * @param tm Normalized broken-down time.200 * @return Number of seconds since the epoch, not counting leap seconds.201 */202 static time_t _secs_since_epoch(const struct tm *tm)203 {204 return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *205 SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +206 tm->tm_min * SECS_PER_MIN + tm->tm_sec;207 194 } 208 195 … … 305 292 } 306 293 307 /**308 * Which day the week-based year starts on, relative to the first calendar day.309 * E.g. if the year starts on December 31st, the return value is -1.310 *311 * @param Year since 1900.312 * @return Offset of week-based year relative to calendar year.313 */314 static int _wbyear_offset(int year)315 {316 int start_wday = _day_of_week(year, 0, 1);317 return _floor_mod(4 - start_wday, 7) - 3;318 }319 320 /**321 * Returns week-based year of the specified time.322 *323 * @param tm Normalized broken-down time.324 * @return Week-based year.325 */326 static int _wbyear(const struct tm *tm)327 {328 int day = tm->tm_yday - _wbyear_offset(tm->tm_year);329 if (day < 0) {330 /* Last week of previous year. */331 return tm->tm_year - 1;332 }333 if (day > 364 + _is_leap_year(tm->tm_year)) {334 /* First week of next year. */335 return tm->tm_year + 1;336 }337 /* All the other days are in the calendar year. */338 return tm->tm_year;339 }340 341 /**342 * Week number of the year, assuming weeks start on sunday.343 * The first Sunday of January is the first day of week 1;344 * days in the new year before this are in week 0.345 *346 * @param tm Normalized broken-down time.347 * @return The week number (0 - 53).348 */349 static int _sun_week_number(const struct tm *tm)350 {351 int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;352 return (tm->tm_yday - first_day + 7) / 7;353 }354 355 /**356 * Week number of the year, assuming weeks start on monday.357 * If the week containing January 1st has four or more days in the new year,358 * then it is considered week 1. Otherwise, it is the last week of the previous359 * year, and the next week is week 1. Both January 4th and the first Thursday360 * of January are always in week 1.361 *362 * @param tm Normalized broken-down time.363 * @return The week number (1 - 53).364 */365 static int _iso_week_number(const struct tm *tm)366 {367 int day = tm->tm_yday - _wbyear_offset(tm->tm_year);368 if (day < 0) {369 /* Last week of previous year. */370 return 53;371 }372 if (day > 364 + _is_leap_year(tm->tm_year)) {373 /* First week of next year. */374 return 1;375 }376 /* All the other days give correct answer. */377 return (day / 7 + 1);378 }379 380 /**381 * Week number of the year, assuming weeks start on monday.382 * The first Monday of January is the first day of week 1;383 * days in the new year before this are in week 0.384 *385 * @param tm Normalized broken-down time.386 * @return The week number (0 - 53).387 */388 static int _mon_week_number(const struct tm *tm)389 {390 int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;391 return (tm->tm_yday - first_day + 7) / 7;392 }393 394 294 /******************************************************************************/ 395 295 … … 420 320 { 421 321 return (double) (time1 - time0); 422 }423 424 /**425 * This function first normalizes the provided broken-down time426 * (moves all values to their proper bounds) and then tries to427 * calculate the appropriate time_t representation.428 *429 * @param tm Broken-down time.430 * @return time_t representation of the time, undefined value on overflow.431 */432 time_t posix_mktime(struct tm *tm)433 {434 // TODO: take DST flag into account435 // TODO: detect overflow436 437 _normalize_time(tm, 0);438 return _secs_since_epoch(tm);439 322 } 440 323 … … 585 468 } 586 469 return posix_asctime_r(&loctime, buf); 587 }588 589 /**590 * Convert time and date to a string, based on a specified format and591 * current locale.592 *593 * @param s Buffer to write string to.594 * @param maxsize Size of the buffer.595 * @param format Format of the output.596 * @param tm Broken-down time to format.597 * @return Number of bytes written.598 */599 size_t posix_strftime(char *restrict s, size_t maxsize,600 const char *restrict format, const struct tm *restrict tm)601 {602 assert(s != NULL);603 assert(format != NULL);604 assert(tm != NULL);605 606 // TODO: use locale607 static const char *wday_abbr[] = {608 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"609 };610 static const char *wday[] = {611 "Sunday", "Monday", "Tuesday", "Wednesday",612 "Thursday", "Friday", "Saturday"613 };614 static const char *mon_abbr[] = {615 "Jan", "Feb", "Mar", "Apr", "May", "Jun",616 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"617 };618 static const char *mon[] = {619 "January", "February", "March", "April", "May", "June", "July",620 "August", "September", "October", "November", "December"621 };622 623 if (maxsize < 1) {624 return 0;625 }626 627 char *ptr = s;628 size_t consumed;629 size_t remaining = maxsize;630 631 #define append(...) { \632 /* FIXME: this requires POSIX-correct snprintf */ \633 /* otherwise it won't work with non-ascii chars */ \634 consumed = snprintf(ptr, remaining, __VA_ARGS__); \635 if (consumed >= remaining) { \636 return 0; \637 } \638 ptr += consumed; \639 remaining -= consumed; \640 }641 642 #define recurse(fmt) { \643 consumed = posix_strftime(ptr, remaining, fmt, tm); \644 if (consumed == 0) { \645 return 0; \646 } \647 ptr += consumed; \648 remaining -= consumed; \649 }650 651 #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \652 (((hour) == 0) ? 12 : (hour)))653 654 while (*format != '\0') {655 if (*format != '%') {656 append("%c", *format);657 format++;658 continue;659 }660 661 format++;662 if (*format == '0' || *format == '+') {663 // TODO: padding664 format++;665 }666 while (isdigit(*format)) {667 // TODO: padding668 format++;669 }670 if (*format == 'O' || *format == 'E') {671 // TODO: locale's alternative format672 format++;673 }674 675 switch (*format) {676 case 'a':677 append("%s", wday_abbr[tm->tm_wday]); break;678 case 'A':679 append("%s", wday[tm->tm_wday]); break;680 case 'b':681 append("%s", mon_abbr[tm->tm_mon]); break;682 case 'B':683 append("%s", mon[tm->tm_mon]); break;684 case 'c':685 // TODO: locale-specific datetime format686 recurse("%Y-%m-%d %H:%M:%S"); break;687 case 'C':688 append("%02d", (1900 + tm->tm_year) / 100); break;689 case 'd':690 append("%02d", tm->tm_mday); break;691 case 'D':692 recurse("%m/%d/%y"); break;693 case 'e':694 append("%2d", tm->tm_mday); break;695 case 'F':696 recurse("%+4Y-%m-%d"); break;697 case 'g':698 append("%02d", _wbyear(tm) % 100); break;699 case 'G':700 append("%d", _wbyear(tm)); break;701 case 'h':702 recurse("%b"); break;703 case 'H':704 append("%02d", tm->tm_hour); break;705 case 'I':706 append("%02d", TO_12H(tm->tm_hour)); break;707 case 'j':708 append("%03d", tm->tm_yday); break;709 case 'k':710 append("%2d", tm->tm_hour); break;711 case 'l':712 append("%2d", TO_12H(tm->tm_hour)); break;713 case 'm':714 append("%02d", tm->tm_mon); break;715 case 'M':716 append("%02d", tm->tm_min); break;717 case 'n':718 append("\n"); break;719 case 'p':720 append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;721 case 'P':722 append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;723 case 'r':724 recurse("%I:%M:%S %p"); break;725 case 'R':726 recurse("%H:%M"); break;727 case 's':728 append("%ld", _secs_since_epoch(tm)); break;729 case 'S':730 append("%02d", tm->tm_sec); break;731 case 't':732 append("\t"); break;733 case 'T':734 recurse("%H:%M:%S"); break;735 case 'u':736 append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);737 break;738 case 'U':739 append("%02d", _sun_week_number(tm)); break;740 case 'V':741 append("%02d", _iso_week_number(tm)); break;742 case 'w':743 append("%d", tm->tm_wday); break;744 case 'W':745 append("%02d", _mon_week_number(tm)); break;746 case 'x':747 // TODO: locale-specific date format748 recurse("%Y-%m-%d"); break;749 case 'X':750 // TODO: locale-specific time format751 recurse("%H:%M:%S"); break;752 case 'y':753 append("%02d", tm->tm_year % 100); break;754 case 'Y':755 append("%d", 1900 + tm->tm_year); break;756 case 'z':757 // TODO: timezone758 break;759 case 'Z':760 // TODO: timezone761 break;762 case '%':763 append("%%");764 break;765 default:766 /* Invalid specifier, print verbatim. */767 while (*format != '%') {768 format--;769 }770 append("%%");771 break;772 }773 format++;774 }775 776 #undef append777 #undef recurse778 779 return maxsize - remaining;780 470 } 781 471
Note:
See TracChangeset
for help on using the changeset viewer.