Adafruit_RTCLib
Fork of Adafruit_RTCLib by
Diff: DateTime.cpp
- Revision:
- 0:7f90c8e04249
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DateTime.cpp Tue Jul 17 05:49:20 2012 +0000 @@ -0,0 +1,154 @@ +// Code by JeeLabs http://news.jeelabs.org/code/ +// Released to the public domain! Enjoy! + +/* + * Taken from https://github.com/adafruit/RTClib + * and modified for LPC1768 by Neal Horman July 2012 + */ + +#include "DateTime.h" + +#define SECONDS_PER_DAY 86400L +#define SECONDS_FROM_1970_TO_2000 946684800 + +//////////////////////////////////////////////////////////////////////////////// +// utility code, some of this could be exposed in the DateTime API if needed + +static const uint8_t daysInMonth [] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; //has to be const or compiler compaints + +// number of days since 2000/01/01, valid for 2001..2099 +static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) +{ + if (y >= 2000) + y -= 2000; + + uint16_t days = d; + for (uint8_t i = 1; i < m; ++i) + days += daysInMonth[i - 1]; + + if (m > 2 && y % 4 == 0) + ++days; + + return days + 365 * y + (y + 3) / 4 - 1; +} + +static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) +{ + return ((days * 24L + h) * 60 + m) * 60 + s; +} + +//////////////////////////////////////////////////////////////////////////////// +// DateTime implementation - ignores time zones and DST changes +// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second + +DateTime::DateTime (uint32_t t) +{ + t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970 + + ss = t % 60; + t /= 60; + mm = t % 60; + t /= 60; + hh = t % 24; + + uint16_t days = t / 24; + uint8_t leap; + + for (yOff = 0; ; ++yOff) + { + leap = yOff % 4 == 0; + if (days < 365 + leap) + break; + days -= 365 + leap; + } + + for (m = 1; ; ++m) + { + uint8_t daysPerMonth = daysInMonth[m - 1]; + + if (leap && m == 2) + ++daysPerMonth; + if (days < daysPerMonth) + break; + days -= daysPerMonth; + } + d = days + 1; +} + +DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) +{ + if (year >= 2000) + year -= 2000; + yOff = year; + m = month; + d = day; + hh = hour; + mm = min; + ss = sec; +} + +static uint8_t conv2d(const char* p) +{ uint8_t v = 0; + + if ('0' <= *p && *p <= '9') + v = *p - '0'; + + return 10 * v + *++p - '0'; +} + +// A convenient constructor for using "the compiler's time": +// DateTime now (__DATE__, __TIME__); +// NOTE: using PSTR would further reduce the RAM footprint +DateTime::DateTime (const char* date, const char* time) +{ + // sample input: date = "Dec 26 2009", time = "12:34:56" + yOff = conv2d(date + 9); + // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + switch (date[0]) + { + case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break; + case 'F': m = 2; break; + case 'A': m = date[2] == 'r' ? 4 : 8; break; + case 'M': m = date[2] == 'r' ? 3 : 5; break; + case 'S': m = 9; break; + case 'O': m = 10; break; + case 'N': m = 11; break; + case 'D': m = 12; break; + } + + d = conv2d(date + 4); + hh = conv2d(time); + mm = conv2d(time + 3); + ss = conv2d(time + 6); +} + +uint8_t DateTime::dayOfWeek() const +{ uint16_t day = date2days(yOff, m, d); + + return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6 +} + +uint32_t DateTime::unixtime(void) const +{ uint16_t days = date2days(yOff, m, d); + + return time2long(days, hh, mm, ss) + SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000 +} + +#ifdef WANT_RTC_MILLIS +//////////////////////////////////////////////////////////////////////////////// +// RTC_Millis implementation + +long RTC_Millis::offset = 0; + +void RTC_Millis::adjust(const DateTime& dt) +{ + offset = dt.unixtime() - millis() / 1000; +} + +DateTime RTC_Millis::now() +{ + return (uint32_t)(offset + millis() / 1000); +} + +//////////////////////////////////////////////////////////////////////////////// +#endif \ No newline at end of file