Neal Horman / Adafruit_RTCLib

Dependents:   espresso-machine-control SAT_OLED Mbedesclava Mbedmaestra ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DateTime.cpp Source File

DateTime.cpp

00001 // Code by JeeLabs http://news.jeelabs.org/code/
00002 // Released to the public domain! Enjoy!
00003 
00004 /*
00005  * Taken from https://github.com/adafruit/RTClib
00006  * and modified for LPC1768 by Neal Horman July 2012
00007  */
00008 
00009 #include "DateTime.h"
00010 
00011 #define SECONDS_PER_DAY 86400L
00012 #define SECONDS_FROM_1970_TO_2000 946684800
00013 
00014 ////////////////////////////////////////////////////////////////////////////////
00015 // utility code, some of this could be exposed in the DateTime API if needed
00016 
00017 static const uint8_t daysInMonth [] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; //has to be const or compiler compaints
00018 
00019 // number of days since 2000/01/01, valid for 2001..2099
00020 static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d)
00021 {
00022     if (y >= 2000)
00023         y -= 2000;
00024     
00025     uint16_t days = d;
00026     for (uint8_t i = 1; i < m; ++i)
00027         days += daysInMonth[i - 1];
00028     
00029     if (m > 2 && y % 4 == 0)
00030         ++days;
00031     
00032     return days + 365 * y + (y + 3) / 4 - 1;
00033 }
00034 
00035 static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s)
00036 {
00037     return ((days * 24L + h) * 60 + m) * 60 + s;
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////////////////
00041 // DateTime implementation - ignores time zones and DST changes
00042 // NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
00043 
00044 DateTime::DateTime (uint32_t t)
00045 {
00046     t -= SECONDS_FROM_1970_TO_2000;    // bring to 2000 timestamp from 1970
00047 
00048     ss = t % 60;
00049     t /= 60;
00050     mm = t % 60;
00051     t /= 60;
00052     hh = t % 24;
00053     
00054     uint16_t days = t / 24;
00055     uint8_t leap;
00056     
00057     for (yOff = 0; ; ++yOff)
00058     {
00059         leap = yOff % 4 == 0;
00060         if (days < 365 + leap)
00061             break;
00062         days -= 365 + leap;
00063     }
00064     
00065     for (m = 1; ; ++m)
00066     {
00067         uint8_t daysPerMonth = daysInMonth[m - 1];
00068         
00069         if (leap && m == 2)
00070             ++daysPerMonth;
00071         if (days < daysPerMonth)
00072             break;
00073         days -= daysPerMonth;
00074     }
00075     d = days + 1;
00076 }
00077 
00078 DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
00079 {
00080     if (year >= 2000)
00081         year -= 2000;
00082     yOff = year;
00083     m = month;
00084     d = day;
00085     hh = hour;
00086     mm = min;
00087     ss = sec;
00088 }
00089 
00090 static uint8_t conv2d(const char* p)
00091 {   uint8_t v = 0;
00092 
00093     if ('0' <= *p && *p <= '9')
00094         v = *p - '0';
00095         
00096     return 10 * v + *++p - '0';
00097 }
00098 
00099 // A convenient constructor for using "the compiler's time":
00100 //   DateTime now (__DATE__, __TIME__);
00101 // NOTE: using PSTR would further reduce the RAM footprint
00102 DateTime::DateTime (const char* date, const char* time)
00103 {
00104     // sample input: date = "Dec 26 2009", time = "12:34:56"
00105     yOff = conv2d(date + 9);
00106     // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 
00107     switch (date[0])
00108     {
00109         case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
00110         case 'F': m = 2; break;
00111         case 'A': m = date[2] == 'r' ? 4 : 8; break;
00112         case 'M': m = date[2] == 'r' ? 3 : 5; break;
00113         case 'S': m = 9; break;
00114         case 'O': m = 10; break;
00115         case 'N': m = 11; break;
00116         case 'D': m = 12; break;
00117     }
00118     
00119     d = conv2d(date + 4);
00120     hh = conv2d(time);
00121     mm = conv2d(time + 3);
00122     ss = conv2d(time + 6);
00123 }
00124 
00125 uint8_t DateTime::dayOfWeek() const
00126 {   uint16_t day = date2days(yOff, m, d);
00127 
00128     return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
00129 }
00130 
00131 uint32_t DateTime::unixtime(void) const
00132 {   uint16_t days = date2days(yOff, m, d);
00133     
00134     return time2long(days, hh, mm, ss) + SECONDS_FROM_1970_TO_2000;  // seconds from 1970 to 2000
00135 }
00136 
00137 #ifdef WANT_RTC_MILLIS
00138 ////////////////////////////////////////////////////////////////////////////////
00139 // RTC_Millis implementation
00140 
00141 long RTC_Millis::offset = 0;
00142 
00143 void RTC_Millis::adjust(const DateTime& dt)
00144 {
00145     offset = dt.unixtime() - millis() / 1000;
00146 }
00147 
00148 DateTime RTC_Millis::now()
00149 {
00150   return (uint32_t)(offset + millis() / 1000);
00151 }
00152 
00153 ////////////////////////////////////////////////////////////////////////////////
00154 #endif