Changeset 3293a94 in mainline for uspace/lib/posix/time.c
- Timestamp:
- 2012-04-23T22:40:02Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7719958
- Parents:
- 4cade47 (diff), d3e3a71 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/time.c
r4cade47 r3293a94 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 … … 408 308 posix_daylight = 0; 409 309 posix_timezone = 0; 410 }411 412 /**413 * Calculate the difference between two times, in seconds.414 *415 * @param time1 First time.416 * @param time0 Second time.417 * @return Time in seconds.418 */419 double posix_difftime(time_t time1, time_t time0)420 {421 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 }440 441 /**442 * Converts a time value to a broken-down UTC time.443 *444 * @param timer Time to convert.445 * @return Normalized broken-down time in UTC, NULL on overflow.446 */447 struct tm *posix_gmtime(const time_t *timer)448 {449 assert(timer != NULL);450 451 static struct tm result;452 return posix_gmtime_r(timer, &result);453 310 } 454 311 … … 484 341 /** 485 342 * Converts a time value to a broken-down local time. 486 *487 * @param timer Time to convert.488 * @return Normalized broken-down time in local timezone, NULL on overflow.489 */490 struct tm *posix_localtime(const time_t *timer)491 {492 static struct tm result;493 return posix_localtime_r(timer, &result);494 }495 496 /**497 * Converts a time value to a broken-down local time.498 343 * 499 344 * @param timer Time to convert. … … 507 352 // currently assumes system and all times are in GMT 508 353 return posix_gmtime_r(timer, result); 509 }510 511 /**512 * Converts broken-down time to a string in format513 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)514 *515 * @param timeptr Broken-down time structure.516 * @return Pointer to a statically allocated string.517 */518 char *posix_asctime(const struct tm *timeptr)519 {520 static char buf[ASCTIME_BUF_LEN];521 return posix_asctime_r(timeptr, buf);522 354 } 523 355 … … 556 388 557 389 /** 558 * Equivalent to asctime(localtime(clock)).559 *560 * @param timer Time to convert.561 * @return Pointer to a statically allocated string holding the date.562 */563 char *posix_ctime(const time_t *timer)564 {565 struct tm *loctime = posix_localtime(timer);566 if (loctime == NULL) {567 return NULL;568 }569 return posix_asctime(loctime);570 }571 572 /**573 390 * Reentrant variant of ctime(). 574 391 * … … 585 402 } 586 403 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); break;737 case 'U':738 append("%02d", _sun_week_number(tm)); break;739 case 'V':740 append("%02d", _iso_week_number(tm)); break;741 case 'w':742 append("%d", tm->tm_wday); break;743 case 'W':744 append("%02d", _mon_week_number(tm)); break;745 case 'x':746 // TODO: locale-specific date format747 recurse("%Y-%m-%d"); break;748 case 'X':749 // TODO: locale-specific time format750 recurse("%H:%M:%S"); break;751 case 'y':752 append("%02d", tm->tm_year % 100); break;753 case 'Y':754 append("%d", 1900 + tm->tm_year); break;755 case 'z':756 // TODO: timezone757 break;758 case 'Z':759 // TODO: timezone760 break;761 case '%':762 append("%%");763 break;764 default:765 /* Invalid specifier, print verbatim. */766 while (*format != '%') {767 format--;768 }769 append("%%");770 break;771 }772 format++;773 }774 775 #undef append776 #undef recurse777 778 return maxsize - remaining;779 404 } 780 405 … … 893 518 stats_task_t *task_stats = stats_get_task(task_get_id()); 894 519 if (task_stats) { 895 total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles); 520 total_cycles = (posix_clock_t) (task_stats->kcycles + 521 task_stats->ucycles); 896 522 free(task_stats); 897 523 task_stats = 0;
Note:
See TracChangeset
for help on using the changeset viewer.