2 time.c - low level time and date functions
3 Copyright (c) Michael Margolis 2009
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 6 Jan 2010 - initial release
20 12 Feb 2010 - fixed leap year calculation error
21 1 Nov 2010 - fixed setTime bug (thanks to Korman for this)
24 #if defined(ARDUINO) && ARDUINO >= 100
32 static tmElements_t tm; // a cache of time elements
33 static time_t cacheTime; // the time the cache was updated
34 static time_t syncInterval = 300; // time sync will be attempted after this many seconds
36 void refreshCache( time_t t){
44 int hour() { // the hour now
48 int hour(time_t t) { // the hour for the given time
53 int hourFormat12() { // the hour now in 12 hour format
54 return hourFormat12(now());
57 int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
60 return 12; // 12 midnight
61 else if( tm.Hour > 12)
67 uint8_t isAM() { // returns true if time now is AM
71 uint8_t isAM(time_t t) { // returns true if given time is AM
75 uint8_t isPM() { // returns true if PM
79 uint8_t isPM(time_t t) { // returns true if PM
80 return (hour(t) >= 12);
87 int minute(time_t t) { // the minute for the given time
96 int second(time_t t) { // the second for the given time
105 int day(time_t t) { // the day for the given time (0-6)
110 int weekday() { // Sunday is day 1
111 return weekday(now());
114 int weekday(time_t t) {
123 int month(time_t t) { // the month for the given time
128 int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
132 int year(time_t t) { // the year for the given time
134 return tmYearToCalendar(tm.Year);
137 /*============================================================================*/
138 /* functions to convert to and from system time */
139 /* These are for interfacing with time serivces and are not normally needed in a sketch */
141 // leap year calulator expects year argument as years offset from 1970
142 #define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
144 static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
\r
146 void breakTime(time_t time, tmElements_t &tm){
147 // break the given time_t into time components
148 // this is a more compact version of the C library localtime function
149 // note that year is offset from 1970 !!!
152 uint8_t month, monthLength;
155 tm.Second = time % 60;
156 time /= 60; // now it is minutes
157 tm.Minute = time % 60;
158 time /= 60; // now it is hours
160 time /= 24; // now it is days
161 tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1
165 while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
168 tm.Year = year; // year is offset from 1970
170 days -= LEAP_YEAR(year) ? 366 : 365;
171 time -= days; // now it is days in this year, starting at 0
176 for (month=0; month<12; month++) {
177 if (month==1) { // february
178 if (LEAP_YEAR(year)) {
184 monthLength = monthDays[month];
187 if (time >= monthLength) {
193 tm.Month = month + 1; // jan is month 1
194 tm.Day = time + 1; // day of month
197 time_t makeTime(tmElements_t &tm){
198 // assemble time elements into time_t
199 // note year argument is offset from 1970 (see macros in time.h to convert to other formats)
200 // previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
205 // seconds from 1970 till 1 jan 00:00:00 of the given year
206 seconds= tm.Year*(SECS_PER_DAY * 365);
207 for (i = 0; i < tm.Year; i++) {
209 seconds += SECS_PER_DAY; // add extra days for leap years
213 // add days for this year, months start from 1
214 for (i = 1; i < tm.Month; i++) {
215 if ( (i == 2) && LEAP_YEAR(tm.Year)) {
216 seconds += SECS_PER_DAY * 29;
218 seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
221 seconds+= (tm.Day-1) * SECS_PER_DAY;
222 seconds+= tm.Hour * SECS_PER_HOUR;
223 seconds+= tm.Minute * SECS_PER_MIN;
227 /*=====================================================*/
228 /* Low level system time functions */
230 static time_t sysTime = 0;
231 static time_t prevMillis = 0;
232 static time_t nextSyncTime = 0;
233 static timeStatus_t Status = timeNotSet;
235 getExternalTime getTimePtr; // pointer to external sync function
236 //setExternalTime setTimePtr; // not used in this version
238 #ifdef TIME_DRIFT_INFO // define this to get drift data
239 time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
244 while( millis() - prevMillis >= 1000){
247 #ifdef TIME_DRIFT_INFO
248 sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
251 if(nextSyncTime <= sysTime){
253 time_t t = getTimePtr();
257 Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
263 void setTime(time_t t){
264 #ifdef TIME_DRIFT_INFO
265 if(sysUnsyncedTime == 0)
266 sysUnsyncedTime = t; // store the time of the first call to set a valid Time
270 nextSyncTime = t + syncInterval;
272 prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
275 void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
276 // year can be given as full four digit year or two digts (2010 or 10 for 2010);
277 //it is converted to years since 1970
288 setTime(makeTime(tm));
291 void adjustTime(long adjustment){
292 sysTime += adjustment;
295 timeStatus_t timeStatus(){ // indicates if time has been set and recently synchronized
299 void setSyncProvider( getExternalTime getTimeFunction){
300 getTimePtr = getTimeFunction;
301 nextSyncTime = sysTime;
302 now(); // this will sync the clock
305 void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
306 syncInterval = interval;