Changeset f7ea5400 in mainline
- Timestamp:
- 2012-08-15T17:52:09Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 16639bb
- Parents:
- 9dec6d4
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/time/cmos-rtc/cmos-rtc.c
r9dec6d4 rf7ea5400 301 301 302 302 time_t cur_time = boottime + uptime_get(); 303 *t = *gmtime(&cur_time); 304 return EOK; 303 return localtime2tm(cur_time, t); 305 304 } 306 305 -
uspace/lib/c/generic/time.c
r9dec6d4 rf7ea5400 841 841 } 842 842 843 struct tm *gmtime(const time_t *timer) 844 { 845 assert(timer != NULL); 846 847 static struct tm result; 843 844 /** Converts a time value to a broken-down UTC time 845 * 846 * @param time Time to convert 847 * @param result Structure to store the result to 848 * 849 * @return EOK or a negative error code 850 */ 851 int utctime2tm(const time_t time, struct tm *restrict result) 852 { 853 assert(result != NULL); 848 854 849 855 /* Set result to epoch. */ 850 result.tm_sec = 0; 851 result.tm_min = 0; 852 result.tm_hour = 0; 853 result.tm_mday = 1; 854 result.tm_mon = 0; 855 result.tm_year = 70; /* 1970 */ 856 857 if (_normalize_time(&result, *timer) == -1) { 858 errno = EOVERFLOW; 859 return NULL; 860 } 861 862 return &result; 863 } 856 result->tm_sec = 0; 857 result->tm_min = 0; 858 result->tm_hour = 0; 859 result->tm_mday = 1; 860 result->tm_mon = 0; 861 result->tm_year = 70; /* 1970 */ 862 863 if (_normalize_time(result, time) == -1) 864 return EOVERFLOW; 865 866 return EOK; 867 } 868 869 /** Converts a time value to a null terminated string of the form 870 * "Wed Jun 30 21:49:08 1993\n" expressed in UTC. 871 * 872 * @param time Time to convert. 873 * @param buf Buffer to store the string to, must be at least 874 * ASCTIME_BUF_LEN bytes long. 875 * 876 * @return EOK or a negative error code. 877 */ 878 int utctime2str(const time_t time, char *restrict buf) 879 { 880 struct tm t; 881 int r; 882 883 if ((r = utctime2tm(time, &t)) != EOK) 884 return r; 885 886 tm2str(&t, buf); 887 return EOK; 888 } 889 864 890 865 891 /** … … 868 894 * 869 895 * @param timeptr Broken-down time structure. 870 * @return Pointer to a statically allocated string. 871 */ 872 char *asctime(const struct tm *timeptr) 873 { 874 static char buf[ASCTIME_BUF_LEN]; 875 896 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN 897 * bytes long. 898 */ 899 void tm2str(const struct tm *restrict timeptr, char *restrict buf) 900 { 876 901 assert(timeptr != NULL); 902 assert(buf != NULL); 877 903 878 904 static const char *wday[] = { … … 890 916 timeptr->tm_min, timeptr->tm_sec, 891 917 1900 + timeptr->tm_year); 892 893 return buf; 894 895 } 896 897 /**898 * Converts a time value to a broken-down local time.899 * 900 * @param timer Time to convert.901 * @return Normalized broken-down time in local timezone, NULL on overflow.902 */ 903 struct tm *localtime(const time_t *timer)918 } 919 920 /** 921 * Converts a time value to a broken-down local time, expressed relative 922 * to the user's specified timezone. 923 * 924 * @param timer Time to convert. 925 * @param result Structure to store the result to. 926 * 927 * @return EOK on success or a negative error code. 928 */ 929 int localtime2tm(const time_t time, struct tm *restrict result) 904 930 { 905 931 // TODO: deal with timezone 906 932 // currently assumes system and all times are in GMT 907 933 908 static struct tm result;909 910 934 /* Set result to epoch. */ 911 result .tm_sec = 0;912 result .tm_min = 0;913 result .tm_hour = 0;914 result .tm_mday = 1;915 result .tm_mon = 0;916 result .tm_year = 70; /* 1970 */917 918 if (_normalize_time( &result, *timer) == -1) {919 errno =EOVERFLOW;920 return NULL; 921 }922 923 return &result; 924 } 925 926 /** 927 * Equivalent to asctime(localtime(clock)).935 result->tm_sec = 0; 936 result->tm_min = 0; 937 result->tm_hour = 0; 938 result->tm_mday = 1; 939 result->tm_mon = 0; 940 result->tm_year = 70; /* 1970 */ 941 942 if (_normalize_time(result, time) == -1) 943 return EOVERFLOW; 944 945 return EOK; 946 } 947 948 /** 949 * Converts the calendar time to a null terminated string 950 * of the form "Wed Jun 30 21:49:08 1993\n" expressed relative to the 951 * user's specified timezone. 928 952 * 929 * @param timer Time to convert. 930 * @return Pointer to a statically allocated string holding the date. 931 */ 932 char *ctime(const time_t *timer) 933 { 934 struct tm *loctime = localtime(timer); 935 if (loctime == NULL) { 936 return NULL; 937 } 938 return asctime(loctime); 953 * @param timer Time to convert. 954 * @param buf Buffer to store the string to. Must be at least 955 * ASCTIME_BUF_LEN bytes long. 956 * 957 * @return EOK on success or a negative error code. 958 */ 959 int localtime2str(const time_t time, char *buf) 960 { 961 struct tm loctime; 962 int r; 963 964 if ((r = localtime2tm(time, &loctime)) != EOK) 965 return r; 966 967 tm2str(&loctime, buf); 968 969 return EOK; 939 970 } 940 971 -
uspace/lib/c/include/sys/time.h
r9dec6d4 rf7ea5400 81 81 82 82 extern time_t mktime(struct tm *tm); 83 extern struct tm *gmtime(const time_t *timer); 84 extern char *asctime(const struct tm *timeptr); 85 extern struct tm *localtime(const time_t *timer); 86 extern char *ctime(const time_t *timer); 83 extern int utctime2tm(const time_t time, struct tm *result); 84 extern int utctime2str(const time_t time, char *buf); 85 extern void tm2str(const struct tm *timeptr, char *buf); 86 extern int localtime2tm(const time_t time, struct tm *result); 87 extern int localtime2str(const time_t time, char *buf); 87 88 extern double difftime(time_t time1, time_t time0); 88 89 extern size_t strftime(char *restrict s, size_t maxsize, -
uspace/lib/posix/time.c
r9dec6d4 rf7ea5400 61 61 */ 62 62 63 64 65 /* Helper functions ***********************************************************/66 67 #define HOURS_PER_DAY (24)68 #define MINS_PER_HOUR (60)69 #define SECS_PER_MIN (60)70 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)71 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)73 74 /**75 * Checks whether the year is a leap year.76 *77 * @param year Year since 1900 (e.g. for 1970, the value is 70).78 * @return true if year is a leap year, false otherwise79 */80 static bool _is_leap_year(time_t year)81 {82 year += 1900;83 84 if (year % 400 == 0)85 return true;86 if (year % 100 == 0)87 return false;88 if (year % 4 == 0)89 return true;90 return false;91 }92 93 /**94 * Returns how many days there are in the given month of the given year.95 * Note that year is only taken into account if month is February.96 *97 * @param year Year since 1900 (can be negative).98 * @param mon Month of the year. 0 for January, 11 for December.99 * @return Number of days in the specified month.100 */101 static int _days_in_month(time_t year, time_t mon)102 {103 assert(mon >= 0 && mon <= 11);104 105 static int month_days[] =106 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };107 108 if (mon == 1) {109 year += 1900;110 /* february */111 return _is_leap_year(year) ? 29 : 28;112 } else {113 return month_days[mon];114 }115 }116 117 /**118 * For specified year, month and day of month, returns which day of that year119 * it is.120 *121 * For example, given date 2011-01-03, the corresponding expression is:122 * _day_of_year(111, 0, 3) == 2123 *124 * @param year Year (year 1900 = 0, can be negative).125 * @param mon Month (January = 0).126 * @param mday Day of month (First day is 1).127 * @return Day of year (First day is 0).128 */129 static int _day_of_year(time_t year, time_t mon, time_t mday)130 {131 static int mdays[] =132 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };133 static int leap_mdays[] =134 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };135 136 return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;137 }138 139 /**140 * Integer division that rounds to negative infinity.141 * Used by some functions in this file.142 *143 * @param op1 Dividend.144 * @param op2 Divisor.145 * @return Rounded quotient.146 */147 static time_t _floor_div(time_t op1, time_t op2)148 {149 if (op1 >= 0 || op1 % op2 == 0) {150 return op1 / op2;151 } else {152 return op1 / op2 - 1;153 }154 }155 156 /**157 * Modulo that rounds to negative infinity.158 * Used by some functions in this file.159 *160 * @param op1 Dividend.161 * @param op2 Divisor.162 * @return Remainder.163 */164 static time_t _floor_mod(time_t op1, time_t op2)165 {166 int div = _floor_div(op1, op2);167 168 /* (a / b) * b + a % b == a */169 /* thus, a % b == a - (a / b) * b */170 171 int result = op1 - div * op2;172 173 /* Some paranoid checking to ensure I didn't make a mistake here. */174 assert(result >= 0);175 assert(result < op2);176 assert(div * op2 + result == op1);177 178 return result;179 }180 181 /**182 * Number of days since the Epoch.183 * Epoch is 1970-01-01, which is also equal to day 0.184 *185 * @param year Year (year 1900 = 0, may be negative).186 * @param mon Month (January = 0).187 * @param mday Day of month (first day = 1).188 * @return Number of days since the Epoch.189 */190 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)191 {192 return (year - 70) * 365 + _floor_div(year - 69, 4) -193 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +194 _day_of_year(year, mon, mday);195 }196 197 /**198 * Which day of week the specified date is.199 *200 * @param year Year (year 1900 = 0).201 * @param mon Month (January = 0).202 * @param mday Day of month (first = 1).203 * @return Day of week (Sunday = 0).204 */205 static int _day_of_week(time_t year, time_t mon, time_t mday)206 {207 /* 1970-01-01 is Thursday */208 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);209 }210 211 /**212 * Normalizes the broken-down time and optionally adds specified amount of213 * seconds.214 *215 * @param tm Broken-down time to normalize.216 * @param sec_add Seconds to add.217 * @return 0 on success, -1 on overflow218 */219 static int _normalize_time(struct tm *tm, time_t sec_add)220 {221 // TODO: DST correction222 223 /* Set initial values. */224 time_t sec = tm->tm_sec + sec_add;225 time_t min = tm->tm_min;226 time_t hour = tm->tm_hour;227 time_t day = tm->tm_mday - 1;228 time_t mon = tm->tm_mon;229 time_t year = tm->tm_year;230 231 /* Adjust time. */232 min += _floor_div(sec, SECS_PER_MIN);233 sec = _floor_mod(sec, SECS_PER_MIN);234 hour += _floor_div(min, MINS_PER_HOUR);235 min = _floor_mod(min, MINS_PER_HOUR);236 day += _floor_div(hour, HOURS_PER_DAY);237 hour = _floor_mod(hour, HOURS_PER_DAY);238 239 /* Adjust month. */240 year += _floor_div(mon, 12);241 mon = _floor_mod(mon, 12);242 243 /* Now the difficult part - days of month. */244 245 /* First, deal with whole cycles of 400 years = 146097 days. */246 year += _floor_div(day, 146097) * 400;247 day = _floor_mod(day, 146097);248 249 /* Then, go in one year steps. */250 if (mon <= 1) {251 /* January and February. */252 while (day > 365) {253 day -= _is_leap_year(year) ? 366 : 365;254 year++;255 }256 } else {257 /* Rest of the year. */258 while (day > 365) {259 day -= _is_leap_year(year + 1) ? 366 : 365;260 year++;261 }262 }263 264 /* Finally, finish it off month per month. */265 while (day >= _days_in_month(year, mon)) {266 day -= _days_in_month(year, mon);267 mon++;268 if (mon >= 12) {269 mon -= 12;270 year++;271 }272 }273 274 /* Calculate the remaining two fields. */275 tm->tm_yday = _day_of_year(year, mon, day + 1);276 tm->tm_wday = _day_of_week(year, mon, day + 1);277 278 /* And put the values back to the struct. */279 tm->tm_sec = (int) sec;280 tm->tm_min = (int) min;281 tm->tm_hour = (int) hour;282 tm->tm_mday = (int) day + 1;283 tm->tm_mon = (int) mon;284 285 /* Casts to work around libc brain-damage. */286 if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {287 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);288 return -1;289 }290 291 tm->tm_year = (int) year;292 return 0;293 }294 295 /******************************************************************************/296 297 63 int posix_daylight; 298 64 long posix_timezone; … … 321 87 struct tm *restrict result) 322 88 { 323 assert(timer != NULL); 324 assert(result != NULL); 325 326 /* Set result to epoch. */ 327 result->tm_sec = 0; 328 result->tm_min = 0; 329 result->tm_hour = 0; 330 result->tm_mday = 1; 331 result->tm_mon = 0; 332 result->tm_year = 70; /* 1970 */ 333 334 if (_normalize_time(result, *timer) == -1) { 335 errno = EOVERFLOW; 89 int rc = utctime2tm(*timer, result); 90 if (rc != EOK) { 91 errno = rc; 336 92 return NULL; 337 93 } 338 94 339 95 return result; 96 } 97 98 /** 99 * Converts a time value to a broken-down UTC time. 100 * (non reentrant version) 101 * 102 * @param timep Time to convert 103 * @return Pointer to a statically allocated structure that stores 104 * the result, NULL in case of error. 105 */ 106 struct tm *posix_gmtime(const time_t *restrict timep) 107 { 108 static struct tm result; 109 110 return posix_gmtime_r(timep, &result); 340 111 } 341 112 … … 353 124 // currently assumes system and all times are in GMT 354 125 return posix_gmtime_r(timer, result); 126 } 127 128 /** 129 * Converts a time value to a broken-down local time. 130 * (non reentrant version) 131 * 132 * @param timep Time to convert. 133 * @return Pointer to a statically allocated structure that stores 134 * the result, NULL in case of error. 135 */ 136 struct tm *posix_localtime(const time_t *restrict timep) 137 { 138 static struct tm result; 139 140 return posix_localtime_r(timep, &result); 355 141 } 356 142 … … 367 153 char *restrict buf) 368 154 { 369 assert(timeptr != NULL); 370 assert(buf != NULL); 371 372 static const char *wday[] = { 373 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 374 }; 375 static const char *mon[] = { 376 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 377 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 378 }; 379 380 snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n", 381 wday[timeptr->tm_wday], 382 mon[timeptr->tm_mon], 383 timeptr->tm_mday, timeptr->tm_hour, 384 timeptr->tm_min, timeptr->tm_sec, 385 1900 + timeptr->tm_year); 386 155 tm2str(timeptr, buf); 387 156 return buf; 388 157 } 389 158 390 159 /** 391 * Reentrant variant of ctime(). 160 * Convers broken-down time to a string in format 161 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 162 * (non reentrant version) 163 * 164 * @param timeptr Broken-down time structure. 165 * @return Pointer to a statically allocated buffer that stores 166 * the result, NULL in case of error. 167 */ 168 char *posix_asctime(const struct tm *restrict timeptr) 169 { 170 static char buf[ASCTIME_BUF_LEN]; 171 172 return posix_asctime_r(timeptr, buf); 173 } 174 175 /** 176 * Converts the calendar time to a string in format 177 * "Sun Jan 1 00:00:00 1970\n" (Obsolete) 392 178 * 393 179 * @param timer Time to convert. 394 180 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN 395 181 * bytes long. 396 * @return Pointer to buf on success, NULL on fa lure.182 * @return Pointer to buf on success, NULL on failure. 397 183 */ 398 184 char *posix_ctime_r(const time_t *timer, char *buf) 399 185 { 400 struct tm loctime; 401 if (posix_localtime_r(timer, &loctime) == NULL) { 186 int r = localtime2str(*timer, buf); 187 if (r != EOK) { 188 errno = r; 402 189 return NULL; 403 190 } 404 return posix_asctime_r(&loctime, buf); 191 192 return buf; 193 } 194 195 /** 196 * Converts the calendar time to a string in format 197 * "Sun Jan 1 00:00:00 1970\n" (Obsolete) 198 * (non reentrant version) 199 * 200 * @param timep Time to convert. 201 * @return Pointer to a statically allocated buffer that stores 202 * the result, NULL in case of error. 203 */ 204 char *posix_ctime(const time_t *timep) 205 { 206 static char buf[ASCTIME_BUF_LEN]; 207 208 return posix_ctime_r(timep, buf); 405 209 } 406 210 -
uspace/lib/posix/time.h
r9dec6d4 rf7ea5400 87 87 extern struct tm *posix_gmtime_r(const time_t *restrict timer, 88 88 struct tm *restrict result); 89 extern struct tm *posix_gmtime(const time_t *restrict timep); 89 90 extern struct tm *posix_localtime_r(const time_t *restrict timer, 90 91 struct tm *restrict result); 92 extern struct tm *posix_localtime(const time_t *restrict timep); 91 93 92 94 /* Formatting Calendar Time */ 93 95 extern char *posix_asctime_r(const struct tm *restrict timeptr, 94 96 char *restrict buf); 97 extern char *posix_asctime(const struct tm *restrict timeptr); 95 98 extern char *posix_ctime_r(const time_t *timer, char *buf); 99 extern char *posix_ctime(const time_t *timer); 96 100 97 101 /* Clocks */ … … 109 113 110 114 #ifndef LIBPOSIX_INTERNAL 111 #define timespec posix_timespec112 #define itimerspec posix_itimerspec113 #define timer_t posix_timer_t115 #define timespec posix_timespec 116 #define itimerspec posix_itimerspec 117 #define timer_t posix_timer_t 114 118 115 #define daylight posix_daylight116 #define timezone posix_timezone117 #define tzname posix_tzname118 #define tzset posix_tzset119 #define daylight posix_daylight 120 #define timezone posix_timezone 121 #define tzname posix_tzname 122 #define tzset posix_tzset 119 123 120 #define gmtime_r posix_gmtime_r 124 #define gmtime_r posix_gmtime_r 125 #define gmtime posix_gmtime 121 126 #define localtime_r posix_localtime_r 127 #define localtime posix_localtime 122 128 123 #define asctime_r posix_asctime_r 124 #define ctime_r posix_ctime_r 129 #define asctime_r posix_asctime_r 130 #define asctime posix_asctime 131 #define ctime_r posix_ctime_r 132 #define ctime posix_ctime 125 133 126 134 #define clock_getres posix_clock_getres
Note:
See TracChangeset
for help on using the changeset viewer.