Changeset a35b458 in mainline for uspace/lib/c/generic/time.c
- Timestamp:
- 2018-03-02T20:10:49Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/time.c
r3061bc1 ra35b458 82 82 { 83 83 year += 1900; 84 84 85 85 if (year % 400 == 0) 86 86 return true; 87 87 88 88 if (year % 100 == 0) 89 89 return false; 90 90 91 91 if (year % 4 == 0) 92 92 return true; 93 93 94 94 return false; 95 95 } … … 110 110 assert(mon >= 0); 111 111 assert(mon <= 11); 112 112 113 113 static int month_days[] = { 114 114 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 115 115 }; 116 116 117 117 if (mon == 1) { 118 118 /* February */ … … 120 120 return is_leap_year(year) ? 29 : 28; 121 121 } 122 122 123 123 return month_days[mon]; 124 124 } … … 144 144 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 145 145 }; 146 146 147 147 static int leap_mdays[] = { 148 148 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 149 149 }; 150 150 151 151 return (is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; 152 152 } … … 166 166 if ((op1 >= 0) || (op1 % op2 == 0)) 167 167 return op1 / op2; 168 168 169 169 return op1 / op2 - 1; 170 170 } … … 183 183 { 184 184 time_t div = floor_div(op1, op2); 185 185 186 186 /* 187 187 * (a / b) * b + a % b == a 188 188 * Thus: a % b == a - (a / b) * b 189 189 */ 190 190 191 191 time_t result = op1 - div * op2; 192 192 193 193 /* Some paranoid checking to ensure there is mistake here. */ 194 194 assert(result >= 0); 195 195 assert(result < op2); 196 196 assert(div * op2 + result == op1); 197 197 198 198 return result; 199 199 } … … 261 261 { 262 262 // TODO: DST correction 263 263 264 264 /* Set initial values. */ 265 265 time_t usec = tm->tm_usec + tv->tv_usec; … … 270 270 time_t mon = tm->tm_mon; 271 271 time_t year = tm->tm_year; 272 272 273 273 /* Adjust time. */ 274 274 sec += floor_div(usec, USECS_PER_SEC); … … 280 280 day += floor_div(hour, HOURS_PER_DAY); 281 281 hour = floor_mod(hour, HOURS_PER_DAY); 282 282 283 283 /* Adjust month. */ 284 284 year += floor_div(mon, 12); 285 285 mon = floor_mod(mon, 12); 286 286 287 287 /* Now the difficult part - days of month. */ 288 288 289 289 /* First, deal with whole cycles of 400 years = 146097 days. */ 290 290 year += floor_div(day, 146097) * 400; 291 291 day = floor_mod(day, 146097); 292 292 293 293 /* Then, go in one year steps. */ 294 294 if (mon <= 1) { … … 305 305 } 306 306 } 307 307 308 308 /* Finally, finish it off month per month. */ 309 309 while (day >= days_in_month(year, mon)) { 310 310 day -= days_in_month(year, mon); 311 311 mon++; 312 312 313 313 if (mon >= 12) { 314 314 mon -= 12; … … 316 316 } 317 317 } 318 318 319 319 /* Calculate the remaining two fields. */ 320 320 tm->tm_yday = day_of_year(year, mon, day + 1); 321 321 tm->tm_wday = day_of_week(year, mon, day + 1); 322 322 323 323 /* And put the values back to the struct. */ 324 324 tm->tm_usec = (int) usec; … … 328 328 tm->tm_mday = (int) day + 1; 329 329 tm->tm_mon = (int) mon; 330 330 331 331 /* Casts to work around POSIX brain-damage. */ 332 332 if (year > ((int) INT_MAX) || year < ((int) INT_MIN)) { … … 334 334 return -1; 335 335 } 336 336 337 337 tm->tm_year = (int) year; 338 338 return 0; … … 363 363 { 364 364 int start_wday = day_of_week(year, 0, 1); 365 365 366 366 return floor_mod(4 - start_wday, 7) - 3; 367 367 } … … 377 377 { 378 378 int day = tm->tm_yday - wbyear_offset(tm->tm_year); 379 379 380 380 if (day < 0) { 381 381 /* Last week of previous year. */ 382 382 return tm->tm_year - 1; 383 383 } 384 384 385 385 if (day > 364 + is_leap_year(tm->tm_year)) { 386 386 /* First week of next year. */ 387 387 return tm->tm_year + 1; 388 388 } 389 389 390 390 /* All the other days are in the calendar year. */ 391 391 return tm->tm_year; … … 405 405 { 406 406 int first_day = (7 - day_of_week(tm->tm_year, 0, 1)) % 7; 407 407 408 408 return (tm->tm_yday - first_day + 7) / 7; 409 409 } … … 425 425 { 426 426 int day = tm->tm_yday - wbyear_offset(tm->tm_year); 427 427 428 428 if (day < 0) { 429 429 /* Last week of previous year. */ 430 430 return 53; 431 431 } 432 432 433 433 if (day > 364 + is_leap_year(tm->tm_year)) { 434 434 /* First week of next year. */ 435 435 return 1; 436 436 } 437 437 438 438 /* All the other days give correct answer. */ 439 439 return (day / 7 + 1); … … 453 453 { 454 454 int first_day = (1 - day_of_week(tm->tm_year, 0, 1)) % 7; 455 455 456 456 return (tm->tm_yday - first_day + 7) / 7; 457 457 } … … 535 535 if (tv1->tv_sec > tv2->tv_sec) 536 536 return true; 537 537 538 538 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec)) 539 539 return true; 540 540 541 541 return false; 542 542 } … … 555 555 if (tv1->tv_sec > tv2->tv_sec) 556 556 return true; 557 557 558 558 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec)) 559 559 return true; 560 560 561 561 return false; 562 562 } … … 582 582 tz->tz_dsttime = DST_NONE; 583 583 } 584 584 585 585 if (clock_conn == NULL) { 586 586 category_id_t cat_id; … … 588 588 if (rc != EOK) 589 589 goto fallback; 590 590 591 591 service_id_t *svc_ids; 592 592 size_t svc_cnt; … … 594 594 if (rc != EOK) 595 595 goto fallback; 596 596 597 597 if (svc_cnt == 0) 598 598 goto fallback; 599 599 600 600 char *svc_name; 601 601 rc = loc_service_get_name(svc_ids[0], &svc_name); … … 603 603 if (rc != EOK) 604 604 goto fallback; 605 605 606 606 service_id_t svc_id; 607 607 rc = loc_service_get_id(svc_name, &svc_id, 0); … … 609 609 if (rc != EOK) 610 610 goto fallback; 611 611 612 612 clock_conn = loc_service_connect(svc_id, INTERFACE_DDF, 613 613 IPC_FLAG_BLOCKING); … … 615 615 goto fallback; 616 616 } 617 617 618 618 struct tm time; 619 619 errno_t rc = clock_dev_time_get(clock_conn, &time); 620 620 if (rc != EOK) 621 621 goto fallback; 622 622 623 623 tv->tv_usec = time.tm_usec; 624 624 tv->tv_sec = mktime(&time); 625 625 626 626 return; 627 627 628 628 fallback: 629 629 getuptime(tv); … … 639 639 goto fallback; 640 640 } 641 641 642 642 void *addr = AS_AREA_ANY; 643 643 rc = physmem_map(faddr, 1, AS_AREA_READ | AS_AREA_CACHEABLE, … … 648 648 goto fallback; 649 649 } 650 650 651 651 ktime = addr; 652 652 } 653 653 654 654 sysarg_t s2 = ktime->seconds2; 655 655 656 656 read_barrier(); 657 657 tv->tv_usec = ktime->useconds; 658 658 659 659 read_barrier(); 660 660 sysarg_t s1 = ktime->seconds1; 661 661 662 662 if (s1 != s2) { 663 663 tv->tv_sec = max(s1, s2); … … 665 665 } else 666 666 tv->tv_sec = s1; 667 667 668 668 return; 669 669 670 670 fallback: 671 671 tv->tv_sec = 0; … … 677 677 struct timeval tv; 678 678 gettimeofday(&tv, NULL); 679 679 680 680 if (tloc) 681 681 *tloc = tv.tv_sec; 682 682 683 683 return tv.tv_sec; 684 684 } … … 706 706 // TODO: take DST flag into account 707 707 // TODO: detect overflow 708 708 709 709 normalize_tm_time(tm, 0); 710 710 return secs_since_epoch(tm); … … 755 755 assert(format != NULL); 756 756 assert(tm != NULL); 757 757 758 758 // TODO: use locale 759 759 760 760 static const char *wday_abbr[] = { 761 761 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 762 762 }; 763 763 764 764 static const char *wday[] = { 765 765 "Sunday", "Monday", "Tuesday", "Wednesday", 766 766 "Thursday", "Friday", "Saturday" 767 767 }; 768 768 769 769 static const char *mon_abbr[] = { 770 770 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 771 771 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 772 772 }; 773 773 774 774 static const char *mon[] = { 775 775 "January", "February", "March", "April", "May", "June", "July", 776 776 "August", "September", "October", "November", "December" 777 777 }; 778 778 779 779 if (maxsize < 1) 780 780 return 0; 781 781 782 782 char *ptr = s; 783 783 size_t consumed; 784 784 size_t remaining = maxsize; 785 785 786 786 while (*format != '\0') { 787 787 if (*format != '%') { … … 790 790 continue; 791 791 } 792 792 793 793 format++; 794 794 if ((*format == '0') || (*format == '+')) { … … 796 796 format++; 797 797 } 798 798 799 799 while (isdigit(*format)) { 800 800 // TODO: padding 801 801 format++; 802 802 } 803 803 804 804 if ((*format == 'O') || (*format == 'E')) { 805 805 // TODO: locale's alternative format 806 806 format++; 807 807 } 808 808 809 809 switch (*format) { 810 810 case 'a': … … 938 938 while (*format != '%') 939 939 format--; 940 940 941 941 APPEND("%%"); 942 942 break; 943 943 } 944 944 945 945 format++; 946 946 } 947 947 948 948 return maxsize - remaining; 949 949 } … … 960 960 { 961 961 assert(result != NULL); 962 962 963 963 /* Set result to epoch. */ 964 964 result->tm_usec = 0; … … 969 969 result->tm_mon = 0; 970 970 result->tm_year = 70; /* 1970 */ 971 971 972 972 if (normalize_tm_time(result, time) == -1) 973 973 return EOVERFLOW; 974 974 975 975 return EOK; 976 976 } … … 993 993 if (ret != EOK) 994 994 return ret; 995 995 996 996 time_tm2str(&tm, buf); 997 997 return EOK; … … 1011 1011 assert(timeptr != NULL); 1012 1012 assert(buf != NULL); 1013 1013 1014 1014 static const char *wday[] = { 1015 1015 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 1016 1016 }; 1017 1017 1018 1018 static const char *mon[] = { 1019 1019 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1020 1020 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 1021 1021 }; 1022 1022 1023 1023 snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n", 1024 1024 wday[timeptr->tm_wday], … … 1043 1043 // TODO: Deal with timezones. 1044 1044 // Currently assumes system and all times are in UTC 1045 1045 1046 1046 /* Set result to epoch. */ 1047 1047 result->tm_usec = 0; … … 1052 1052 result->tm_mon = 0; 1053 1053 result->tm_year = 70; /* 1970 */ 1054 1054 1055 1055 if (normalize_tm_tv(result, tv) == -1) 1056 1056 return EOVERFLOW; 1057 1057 1058 1058 return EOK; 1059 1059 } … … 1097 1097 if (ret != EOK) 1098 1098 return ret; 1099 1099 1100 1100 time_tm2str(&loctime, buf); 1101 1101 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.