Chris Paola
/
gmtime_test
Small test of the gmtime function.
Revision 0:53c251120904, committed 2015-05-10
- Comitter:
- bjblazkowicz
- Date:
- Sun May 10 22:05:28 2015 +0000
- Commit message:
- Initial commit.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmtime_newlib.cpp Sun May 10 22:05:28 2015 +0000 @@ -0,0 +1,159 @@ +/* + * gmtime_r.c + * Original Author: Adapted from tzcode maintained by Arthur David Olson. + * Modifications: + * - Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston + * - Fixed bug in mday computations - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> + * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> + * - Move code from _mktm_r() to gmtime_r() - 05/09/14, Freddie Chopin <freddie_chopin@op.pl> + * - Fixed bug in calculations for dates after year 2069 or before year 1901. Ideas for + * solution taken from musl's __secs_to_tm() - 07/12/2014, Freddie Chopin + * <freddie_chopin@op.pl> + * + * Converts the calendar time pointed to by tim_p into a broken-down time + * expressed as local time. Returns a pointer to a structure containing the + * broken-down time. + */ + +// *** ChrisP 5/10/15: Code taken from http://sourceware.org/newlib/; modified slightly to compile on mbed.org *** + +#include "mbed.h" + +/* move epoch from 01.01.1970 to 01.03.2000 - this is the first day of new + * 400-year long cycle, right after additional day of leap year. This adjustment + * is required only for date calculation, so instead of modifying time_t value + * (which would require 64-bit operations to work correctly) it's enough to + * adjust the calculated number of days since epoch. */ +#define EPOCH_ADJUSTMENT_DAYS 11017 +/* year to which the adjustment was made */ +#define ADJUSTED_EPOCH_YEAR 2000 +/* 1st March of 2000 is Wednesday */ +#define ADJUSTED_EPOCH_WDAY 3 +/* there are 97 leap years in 400-year periods. ((400 - 97) * 365 + 97 * 366) */ +#define DAYS_PER_400_YEARS 146097L +/* there are 24 leap years in 100-year periods. ((100 - 24) * 365 + 24 * 366) */ +#define DAYS_PER_100_YEARS 36524L +/* there is one leap year every 4 years */ +#define DAYS_PER_4_YEARS (3 * 365 + 366) +/* number of days in a non-leap year */ +#define DAYS_PER_YEAR 365 +/* number of days in January */ +#define DAYS_IN_JANUARY 31 +/* number of days in non-leap February */ +#define DAYS_IN_FEBRUARY 28 + +#define SECSPERMIN 60L +#define MINSPERHOUR 60L +#define HOURSPERDAY 24L +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY) +#define DAYSPERWEEK 7 +#define MONSPERYEAR 12 + +#define YEAR_BASE 1900 +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY 4 +#define EPOCH_YEARS_SINCE_LEAP 2 +#define EPOCH_YEARS_SINCE_CENTURY 70 +#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370 + +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + +const int __month_lengths[2][MONSPERYEAR] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +} ; + +struct tm * +gmtime_newlib(const time_t* tim_p, struct tm* res) +{ + long days, rem; + const time_t lcltime = *tim_p; + int year, month, yearday, weekday; + int years400, years100, years4, remainingyears; + int yearleap; + const int *ip; + + days = ((long)lcltime) / SECSPERDAY - EPOCH_ADJUSTMENT_DAYS; + rem = ((long)lcltime) % SECSPERDAY; + if (rem < 0) + { + rem += SECSPERDAY; + --days; + } + + /* compute hour, min, and sec */ + res->tm_hour = (int) (rem / SECSPERHOUR); + rem %= SECSPERHOUR; + res->tm_min = (int) (rem / SECSPERMIN); + res->tm_sec = (int) (rem % SECSPERMIN); + + /* compute day of week */ + if ((weekday = ((ADJUSTED_EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) + weekday += DAYSPERWEEK; + res->tm_wday = weekday; + + /* compute year & day of year */ + years400 = days / DAYS_PER_400_YEARS; + days -= years400 * DAYS_PER_400_YEARS; + /* simplify by making the values positive */ + if (days < 0) + { + days += DAYS_PER_400_YEARS; + --years400; + } + + years100 = days / DAYS_PER_100_YEARS; + if (years100 == 4) /* required for proper day of year calculation */ + --years100; + days -= years100 * DAYS_PER_100_YEARS; + years4 = days / DAYS_PER_4_YEARS; + days -= years4 * DAYS_PER_4_YEARS; + remainingyears = days / DAYS_PER_YEAR; + if (remainingyears == 4) /* required for proper day of year calculation */ + --remainingyears; + days -= remainingyears * DAYS_PER_YEAR; + + year = ADJUSTED_EPOCH_YEAR + years400 * 400 + years100 * 100 + years4 * 4 + + remainingyears; + + /* If remainingyears is zero, it means that the years were completely + * "consumed" by modulo calculations by 400, 100 and 4, so the year is: + * 1. a multiple of 4, but not a multiple of 100 or 400 - it's a leap year, + * 2. a multiple of 4 and 100, but not a multiple of 400 - it's not a leap + * year, + * 3. a multiple of 4, 100 and 400 - it's a leap year. + * If years4 is non-zero, it means that the year is not a multiple of 100 or + * 400 (case 1), so it's a leap year. If years100 is zero (and years4 is zero + * - due to short-circuiting), it means that the year is a multiple of 400 + * (case 3), so it's also a leap year. */ + yearleap = remainingyears == 0 && (years4 != 0 || years100 == 0); + + /* adjust back to 1st January */ + yearday = days + DAYS_IN_JANUARY + DAYS_IN_FEBRUARY + yearleap; + if (yearday >= DAYS_PER_YEAR + yearleap) + { + yearday -= DAYS_PER_YEAR + yearleap; + ++year; + } + res->tm_yday = yearday; + res->tm_year = year - YEAR_BASE; + + /* Because "days" is the number of days since 1st March, the additional leap + * day (29th of February) is the last possible day, so it doesn't matter much + * whether the year is actually leap or not. */ + ip = __month_lengths[1]; + month = 2; + while (days >= ip[month]) + { + days -= ip[month]; + if (++month >= MONSPERYEAR) + month = 0; + } + res->tm_mon = month; + res->tm_mday = days + 1; + + res->tm_isdst = 0; + + return (res); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmtime_newlib.h Sun May 10 22:05:28 2015 +0000 @@ -0,0 +1,8 @@ + +#ifndef GMTIME_NEWLIB_H +#define GMTIME_NEWLIB_H + +struct tm * +gmtime_newlib(const time_t* tim_p, struct tm* res); + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun May 10 22:05:28 2015 +0000 @@ -0,0 +1,27 @@ +#include "mbed.h" +#include "gmtime_newlib.h" + +Serial console(USBTX, USBRX); + +int main() +{ + console.baud(9600); + + // Set time to Tue, 10 Nov 2015 14:00:00 GMT + set_time(1447164000); + + time_t rawTime; + time(&rawTime); + + // Prints: time_t: 1447164000, h:13773, m:1377, s:537067520 + struct tm *parsedUsingMbed = gmtime(&rawTime); + console.printf("time_t: %d, h:%d, m:%d, s:%d\r\n", rawTime, parsedUsingMbed->tm_hour, parsedUsingMbed->tm_min, parsedUsingMbed->tm_sec); + + // Prints: time_t: 1447164000, h:14, m:0, s:0 + struct tm parsedUsingNewlib; + gmtime_newlib(&rawTime, &parsedUsingNewlib); + console.printf("time_t: %d, h:%d, m:%d, s:%d\r\n", rawTime, parsedUsingNewlib.tm_hour, parsedUsingNewlib.tm_min, parsedUsingNewlib.tm_sec); + + while(1) + ; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun May 10 22:05:28 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/8ab26030e058 \ No newline at end of file