Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yuii #170

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open

Yuii #170

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ there are also functions to return the hour in 12-hour format
hourFormat12(); // the hour now in 12 hour format
isAM(); // returns true if time now is AM
isPM(); // returns true if time now is PM

now(); // returns the current time as seconds since Jan 1 1970
```

The time and date functions can take an optional parameter for the time. This prevents
Expand All @@ -60,13 +58,24 @@ month(t); // the month for the given time t
year(t); // the year for the given time t
```

There are also two functions that return the number of milliseconds left-over. Care
should be taken when using this value since there are no functions to set the time
with sub-second accuracy and the value may jump when the time is synchronized.
However, it is always consistent with the current time. To access these functions,
you have to `#define TIMELIB_ENABLE_MILLIS` in your sketch.

```c
time_t t = now(uint32_t& m) // store the current time in time variable t and milliseconds in m
millisecond(); // the millisecond now (0-999)
```

Functions for managing the timer services are:

```c
setTime(t); // set the system time to the give time t
setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr
// (2010 or 10 sets year to 2010)
adjustTime(adjustment); // adjust system time by adding the adjustment value
adjustTime(adjustment); // adjust system time by adding the adjustment value (in seconds)
timeStatus(); // indicates if time has been set and recently synchronized
// returns one of the following enumerations:
timeNotSet // the time has never been set, the clock started on Jan 1, 1970
Expand Down
174 changes: 96 additions & 78 deletions Time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,20 @@
#include <WProgram.h>
#endif

#define TIMELIB_ENABLE_MILLIS
#include "TimeLib.h"

static tmElements_t tm; // a cache of time elements
// Convert days since epoch to week day. Sunday is day 1.
#define DAYS_TO_WDAY(x) (((x) + 4) % 7) + 1

static tmElements_t cacheElements; // a cache of time elements
static time_t cacheTime; // the time the cache was updated
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds

void refreshCache(time_t t) {
if (t != cacheTime) {
breakTime(t, tm);
cacheTime = t;
breakTime(t, cacheElements);
cacheTime = t;
}
}

Expand All @@ -52,7 +56,7 @@ int hour() { // the hour now

int hour(time_t t) { // the hour for the given time
refreshCache(t);
return tm.Hour;
return cacheElements.Hour;
}

int hourFormat12() { // the hour now in 12 hour format
Expand All @@ -61,12 +65,12 @@ int hourFormat12() { // the hour now in 12 hour format

int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
refreshCache(t);
if( tm.Hour == 0 )
if( cacheElements.Hour == 0 )
return 12; // 12 midnight
else if( tm.Hour > 12)
return tm.Hour - 12 ;
else if( cacheElements.Hour > 12)
return cacheElements.Hour - 12 ;
else
return tm.Hour ;
return cacheElements.Hour ;
}

uint8_t isAM() { // returns true if time now is AM
Expand All @@ -91,7 +95,7 @@ int minute() {

int minute(time_t t) { // the minute for the given time
refreshCache(t);
return tm.Minute;
return cacheElements.Minute;
}

int second() {
Expand All @@ -100,7 +104,13 @@ int second() {

int second(time_t t) { // the second for the given time
refreshCache(t);
return tm.Second;
return cacheElements.Second;
}

int millisecond() {
uint32_t ms;
now(ms);
return (int)ms;
}

int day(){
Expand All @@ -109,16 +119,16 @@ int day(){

int day(time_t t) { // the day for the given time (0-6)
refreshCache(t);
return tm.Day;
return cacheElements.Day;
}

int weekday() { // Sunday is day 1
return weekday(now());
return weekday(now());
}

int weekday(time_t t) {
refreshCache(t);
return tm.Wday;
return cacheElements.Wday;
}

int month(){
Expand All @@ -127,7 +137,7 @@ int month(){

int month(time_t t) { // the month for the given time
refreshCache(t);
return tm.Month;
return cacheElements.Month;
}

int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
Expand All @@ -136,7 +146,7 @@ int year() { // as in Processing, the full four digit year: (2009, 2010 etc)

int year(time_t t) { // the year for the given time
refreshCache(t);
return tmYearToCalendar(tm.Year);
return tmYearToCalendar(cacheElements.Year);
}

/*============================================================================*/
Expand All @@ -145,60 +155,59 @@ int year(time_t t) { // the year for the given time

// leap year calculator expects year argument as years offset from 1970
#define LEAP_YEAR(Y) ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) )
#define daysInYear(year) ((time_t) (LEAP_YEAR(year) ? 366 : 365))

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
void breakTime(time_t timeInput, tmElements_t &tm){
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

void breakTime(time_t time, tmElements_t &tm){
// break the given time_t into time components
// this is a more compact version of the C library localtime function
// note that year is offset from 1970 !!!

uint8_t year;
uint8_t month, monthLength;
uint32_t time;
unsigned long days;
uint8_t period;
time_t length;

time = (uint32_t)timeInput;
tm.Second = time % 60;
time /= 60; // now it is minutes
tm.Minute = time % 60;
time /= 60; // now it is hours
tm.Hour = time % 24;
time /= 24; // now it is days
tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1

year = 0;
days = 0;
while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
year++;
time /= 24; // now it is days since 1 Jan 1970

// if the number of days since epoch matches cacheTime, then can take date
// elements from cacheElements and avoid expensive calculation.
if (time == (cacheTime / SECS_PER_DAY)) {
if (&tm != &cacheElements) { // check whether tm is actually cacheElements
tm.Wday = cacheElements.Wday;
tm.Day = cacheElements.Day;
tm.Month = cacheElements.Month;
tm.Year = cacheElements.Year;
}
return;
}
tm.Year = year; // year is offset from 1970

days -= LEAP_YEAR(year) ? 366 : 365;
time -= days; // now it is days in this year, starting at 0

tm.Wday = DAYS_TO_WDAY(time);

days=0;
month=0;
monthLength=0;
for (month=0; month<12; month++) {
if (month==1) { // february
if (LEAP_YEAR(year)) {
monthLength=29;
} else {
monthLength=28;
}
} else {
monthLength = monthDays[month];
}

if (time >= monthLength) {
time -= monthLength;
} else {
break;
}
period = 0;
while (time >= (length = daysInYear(period)))
{
time -= length;
period++;
}
tm.Month = month + 1; // jan is month 1
tm.Day = time + 1; // day of month
tm.Year = period; // year is offset from 1970
// time is now days since 1 Jan of the year

bool leap_year = LEAP_YEAR(period);
period = 0;
while (period < 12 && time >= (length = monthDays[period] + (leap_year && period==1)))
{
time -= length;
period++;
}
tm.Month = period + 1; // jan is month 1
// time is now days since the 1st day of the month

tm.Day = time + 1; // day of month
}

time_t makeTime(const tmElements_t &tm){
Expand All @@ -210,7 +219,7 @@ time_t makeTime(const tmElements_t &tm){
uint32_t seconds;

// seconds from 1970 till 1 jan 00:00:00 of the given year
seconds= tm.Year*(SECS_PER_DAY * 365);
seconds = SECS_PER_DAY * (365 * tm.Year);
for (i = 0; i < tm.Year; i++) {
if (LEAP_YEAR(i)) {
seconds += SECS_PER_DAY; // add extra days for leap years
Expand All @@ -234,9 +243,9 @@ time_t makeTime(const tmElements_t &tm){
/*=====================================================*/
/* Low level system time functions */

static uint32_t sysTime = 0;
static time_t sysTime = 0;
static uint32_t prevMillis = 0;
static uint32_t nextSyncTime = 0;
static time_t nextSyncTime = 0;
static timeStatus_t Status = timeNotSet;

getExternalTime getTimePtr; // pointer to external sync function
Expand All @@ -248,9 +257,16 @@ time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync


time_t now() {
// calculate number of seconds passed since last call to now()
while (millis() - prevMillis >= 1000) {
// millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference
uint32_t sysTimeMillis;
return now(sysTimeMillis);
}

time_t now(uint32_t& sysTimeMillis) {
// calculate number of seconds passed since last call to now()
while ((sysTimeMillis = millis() - prevMillis) >= 1000) {
// millis() and prevMillis are both unsigned ints thus the subtraction will
// always result in a positive difference. This is OK since it corrects for
// wrap-around and millis() is monotonic.
sysTime++;
prevMillis += 1000;
#ifdef TIME_DRIFT_INFO
Expand All @@ -268,7 +284,7 @@ time_t now() {
}
}
}
return (time_t)sysTime;
return sysTime;
}

void setTime(time_t t) {
Expand All @@ -277,26 +293,28 @@ void setTime(time_t t) {
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
#endif

sysTime = (uint32_t)t;
nextSyncTime = (uint32_t)t + syncInterval;
sysTime = t;
nextSyncTime = t + (time_t) syncInterval;
Status = timeSet;
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
}

void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
//it is converted to years since 1970
if( yr > 99)
yr = yr - 1970;
void setTime(int hr, int min, int sec, int dy, int mnth, int yr) {
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
// it is converted to years since 1970
if (yr > 99)
yr = CalendarYrToTm(yr);
else
yr += 30;
tm.Year = yr;
tm.Month = mnth;
tm.Day = dy;
tm.Hour = hr;
tm.Minute = min;
tm.Second = sec;
setTime(makeTime(tm));
yr = tmYearToY2k(yr);
cacheElements.Year = yr;
cacheElements.Month = mnth;
cacheElements.Day = dy;
cacheElements.Hour = hr;
cacheElements.Minute = min;
cacheElements.Second = sec;
cacheTime = makeTime(cacheElements);
cacheElements.Wday = DAYS_TO_WDAY(cacheTime / SECS_PER_DAY);
setTime(cacheTime);
}

void adjustTime(long adjustment) {
Expand All @@ -309,7 +327,7 @@ timeStatus_t timeStatus() {
return Status;
}

void setSyncProvider( getExternalTime getTimeFunction){
void setSyncProvider(getExternalTime getTimeFunction){
getTimePtr = getTimeFunction;
nextSyncTime = sysTime;
now(); // this will sync the clock
Expand Down
6 changes: 6 additions & 0 deletions TimeLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ int minute(); // the minute now
int minute(time_t t); // the minute for the given time
int second(); // the second now
int second(time_t t); // the second for the given time
#ifdef TIMELIB_ENABLE_MILLIS
int millisecond(); // the millisecond now
#endif
int day(); // the day now
int day(time_t t); // the day for the given time
int weekday(); // the weekday now (Sunday is day 1)
Expand All @@ -118,6 +121,9 @@ int year(); // the full four digit year: (2009, 2010 etc)
int year(time_t t); // the year for the given time

time_t now(); // return the current time as seconds since Jan 1 1970
#ifdef TIMELIB_ENABLE_MILLIS
time_t now(uint32_t& sysTimeMillis); // return the current time as seconds and milliseconds since Jan 1 1970
#endif
void setTime(time_t t);
void setTime(int hr,int min,int sec,int day, int month, int yr);
void adjustTime(long adjustment);
Expand Down
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ time_t KEYWORD1
# Methods and Functions (KEYWORD2)
#######################################
now KEYWORD2
millisecond KEYWORD2
second KEYWORD2
minute KEYWORD2
hour KEYWORD2
Expand Down