Exposed date time internal functions for use by others.

Fixed datetime add minutes function for times at beginning and end of day.
This commit is contained in:
skarg
2013-06-11 03:09:56 +00:00
parent 13d58298ea
commit c1e9558655
2 changed files with 206 additions and 84 deletions
+35 -8
View File
@@ -89,8 +89,35 @@ extern "C" {
uint8_t hundredths);
/* utility test for validity */
bool datetime_is_valid(
BACNET_DATE * bdate,
BACNET_TIME * btime);
BACNET_DATE *bdate,
BACNET_TIME *btime);
bool datetime_time_is_valid(
BACNET_TIME *btime);
bool datetime_date_is_valid(
BACNET_DATE *bdate);
/* date and time calculations and summaries */
uint32_t datetime_days_since_epoch(
BACNET_DATE *bdate);
void datetime_days_since_epoch_into_date(
uint32_t days,
BACNET_DATE *bdate);
bool datetime_is_leap_year(
uint16_t year);
uint8_t datetime_month_days(
uint16_t year,
uint8_t month);
uint8_t datetime_day_of_week(
uint16_t year,
uint8_t month,
uint8_t day);
bool datetime_ymd_is_valid(
uint16_t year,
uint8_t month,
uint8_t day);
uint32_t datetime_seconds_since_midnight(
BACNET_TIME *btime);
uint16_t datetime_minutes_since_midnight(
BACNET_TIME *btime);
/* utility comparison functions:
if the date/times are the same, return is 0
@@ -108,14 +135,14 @@ extern "C" {
/* utility copy functions */
void datetime_copy_date(
BACNET_DATE * date1,
BACNET_DATE * date2);
BACNET_DATE * dest,
BACNET_DATE * src);
void datetime_copy_time(
BACNET_TIME * time1,
BACNET_TIME * time2);
BACNET_TIME * dest,
BACNET_TIME * src);
void datetime_copy(
BACNET_DATE_TIME * datetime1,
BACNET_DATE_TIME * datetime2);
BACNET_DATE_TIME * dest,
BACNET_DATE_TIME * src);
/* utility add or subtract minutes function */
void datetime_add_minutes(
+171 -76
View File
@@ -55,8 +55,7 @@
time or date may be interpreted as "any" or "don't care"
*/
static bool is_leap_year(
bool datetime_is_leap_year(
uint16_t year)
{
if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
@@ -65,40 +64,56 @@ static bool is_leap_year(
return (false);
}
static uint8_t month_days(
uint8_t datetime_month_days(
uint16_t year,
uint8_t month)
{
/* note: start with a zero in the first element to save us from a
month - 1 calculation in the lookup */
int month_days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
/* return value */
uint8_t days = 0;
/* February */
if ((month == 2) && is_leap_year(year))
return 29;
else if (month >= 1 && month <= 12)
return (uint8_t) month_days[month];
else
return 0;
if ((month == 2) && datetime_is_leap_year(year)) {
days = 29;
} else if (month >= 1 && month <= 12) {
days = (uint8_t) month_days[month];
}
return days;
}
static bool date_is_valid(
bool datetime_ymd_is_valid(
uint16_t year,
uint8_t month,
uint8_t day)
{
bool status = false; /* true if value date */
uint8_t monthdays; /* days in a month */
bool status = false; /* true if value date */
uint8_t monthdays = 0; /* days in a month */
monthdays = month_days(year, month);
if ((year >= 1900) && (monthdays) && (day >= 1) && (day <= monthdays)) {
monthdays = datetime_month_days(year, month);
if ((year >= 1900) && (monthdays > 0) &&
(day >= 1) && (day <= monthdays)) {
status = true;
}
return status;
}
bool datetime_date_is_valid(
BACNET_DATE *bdate)
{
bool status = false; /* true if value date */
if (bdate) {
status = datetime_ymd_is_valid(bdate->year, bdate->month, bdate->day);
}
return status;
}
static uint32_t days_since_epoch(
uint16_t year,
uint8_t month,
@@ -108,14 +123,14 @@ static uint32_t days_since_epoch(
uint16_t years = 0; /* loop counter for years */
uint8_t months = 0; /* loop counter for months */
if (date_is_valid(year, month, day)) {
if (datetime_ymd_is_valid(year, month, day)) {
for (years = 1900; years < year; years++) {
days += 365;
if (is_leap_year(years))
if (datetime_is_leap_year(years))
days++;
}
for (months = 1; months < month; months++) {
days += month_days(years, months);
days += datetime_month_days(years, months);
}
days += (day - 1);
}
@@ -123,7 +138,19 @@ static uint32_t days_since_epoch(
return (days);
}
static void days_since_epoch_into_ymd(
uint32_t datetime_days_since_epoch(
BACNET_DATE *bdate)
{
uint32_t days = 0;
if (bdate) {
days = days_since_epoch(bdate->year, bdate->month, bdate->day);
}
return days;
}
void days_since_epoch_into_ymd(
uint32_t days,
uint16_t * pYear,
uint8_t * pMonth,
@@ -134,16 +161,16 @@ static void days_since_epoch_into_ymd(
uint8_t day = 1;
while (days >= 365) {
if ((is_leap_year(year)) && (days == 365))
if ((datetime_is_leap_year(year)) && (days == 365))
break;
days -= 365;
if (is_leap_year(year))
if (datetime_is_leap_year(year))
--days;
year++;
}
while (days >= (uint32_t) month_days(year, month)) {
days -= month_days(year, month);
while (days >= (uint32_t) datetime_month_days(year, month)) {
days -= datetime_month_days(year, month);
month++;
}
@@ -159,9 +186,21 @@ static void days_since_epoch_into_ymd(
return;
}
void datetime_days_since_epoch_into_date(
uint32_t days,
BACNET_DATE *bdate)
{
uint16_t year = 0;
uint8_t month = 0;
uint8_t day = 0;
days_since_epoch_into_ymd(days, &year, &month, &day);
datetime_set_date(bdate, year, month, day);
}
/* Jan 1, 1900 is a Monday */
/* wday 1=Monday...7=Sunday */
static uint8_t day_of_week(
uint8_t datetime_day_of_week(
uint16_t year,
uint8_t month,
uint8_t day)
@@ -169,16 +208,16 @@ static uint8_t day_of_week(
return (uint8_t) ((days_since_epoch(year, month, day) % 7) + 1);
}
static bool time_is_valid(
uint8_t hour,
uint8_t min,
uint8_t sec,
uint8_t hundredths)
bool datetime_time_is_valid(
BACNET_TIME *btime)
{
bool status = false;
if ((hour < 24) && (min < 60) && (sec < 60) && (hundredths < 100)) {
status = true;
if (btime) {
if ((btime->hour < 24) && (btime->min < 60) && (btime->sec < 60) &&
(btime->hundredths < 100)) {
status = true;
}
}
return status;
@@ -193,24 +232,10 @@ static bool time_is_valid(
* @return true if the date and time are valid
*/
bool datetime_is_valid(
BACNET_DATE * bdate,
BACNET_TIME * btime)
BACNET_DATE *bdate,
BACNET_TIME *btime)
{
bool status = false; /* return value */
/* get the number of days in the month, and check for valid month too */
if (bdate) {
status = date_is_valid(bdate->year, bdate->month, bdate->day);
if (status && btime) {
status =
time_is_valid(btime->hour, btime->min, btime->sec,
btime->hundredths);
} else {
status = false;
}
}
return status;
return datetime_date_is_valid(bdate) && datetime_time_is_valid(btime);
}
@@ -320,7 +345,7 @@ void datetime_set_date(
bdate->year = year;
bdate->month = month;
bdate->day = day;
bdate->wday = day_of_week(year, month, day);
bdate->wday = datetime_day_of_week(year, month, day);
}
}
@@ -370,7 +395,7 @@ void datetime_set_values(
bdatetime->date.year = year;
bdatetime->date.month = month;
bdatetime->date.day = day;
bdatetime->date.wday = day_of_week(year, month, day);
bdatetime->date.wday = datetime_day_of_week(year, month, day);
bdatetime->time.hour = hour;
bdatetime->time.min = minute;
bdatetime->time.sec = seconds;
@@ -386,6 +411,13 @@ static uint32_t seconds_since_midnight(
return ((hours * 60 * 60) + (minutes * 60) + seconds);
}
static uint16_t minutes_since_midnight(
uint8_t hours,
uint8_t minutes)
{
return ((hours * 60) + minutes);
}
static void seconds_since_midnight_into_hms(
uint32_t seconds,
uint8_t * pHours,
@@ -408,6 +440,47 @@ static void seconds_since_midnight_into_hms(
*pSeconds = (uint8_t) seconds;
}
/** Calculates the number of seconds since midnight
*
* @param btime [in] BACNET_TIME containing the time to convert
*
* @return seconds since midnight
*/
uint32_t datetime_seconds_since_midnight(
BACNET_TIME *btime)
{
uint32_t seconds = 0;
if (btime) {
seconds = seconds_since_midnight(
btime->hour,
btime->min,
btime->sec);
}
return seconds;
}
/** Calculates the number of minutes since midnight
*
* @param btime [in] BACNET_TIME containing the time to convert
*
* @return minutes since midnight
*/
uint16_t datetime_minutes_since_midnight(
BACNET_TIME *btime)
{
uint32_t minutes = 0;
if (btime) {
minutes = minutes_since_midnight(
btime->hour,
btime->min);
}
return minutes;
}
/** Utility to add or subtract minutes to a BACnet DateTime structure
*
* @param bdatetime [in] the starting date and time
@@ -425,26 +498,38 @@ void datetime_add_minutes(
bdatetime_minutes =
seconds_since_midnight(bdatetime->time.hour, bdatetime->time.min,
bdatetime->time.sec) / 60;
bdatetime_days =
days_since_epoch(bdatetime->date.year, bdatetime->date.month,
bdatetime->date.day);
bdatetime_days = datetime_days_since_epoch(&bdatetime->date);
/* add */
/* more minutes than in a day? */
days = minutes / (24 * 60);
bdatetime_days += days;
minutes -= (days * 24 * 60);
bdatetime_minutes += minutes;
days = bdatetime_minutes / (24 * 60);
bdatetime_days += days;
/* less minutes - previous day? */
if (minutes < 0) {
/* convert to positive for easier math */
minutes *= -1;
if (minutes > bdatetime_minutes) {
/* previous day */
bdatetime_days -= 1;
bdatetime_minutes += ((24 * 60) - minutes);
} else {
bdatetime_minutes -= minutes;
days = bdatetime_minutes / (24 * 60);
bdatetime_days += days;
bdatetime_minutes -= (days * 24 * 60);
}
} else {
/* more days than current datetime? */
bdatetime_minutes += minutes;
days = bdatetime_minutes / (24 * 60);
bdatetime_days += days;
bdatetime_minutes -= (days * 24 * 60);
}
/* convert bdatetime from seconds and days */
seconds_since_midnight_into_hms(bdatetime_minutes * 60,
&bdatetime->time.hour, &bdatetime->time.min, NULL);
days_since_epoch_into_ymd(bdatetime_days, &bdatetime->date.year,
&bdatetime->date.month, &bdatetime->date.day);
bdatetime->date.wday =
day_of_week(bdatetime->date.year, bdatetime->date.month,
bdatetime->date.day);
datetime_days_since_epoch_into_date(bdatetime_days, &bdatetime->date);
}
bool datetime_wildcard(
@@ -662,10 +747,20 @@ void testBACnetDateTimeAdd(
datetime_set_values(&test_bdatetime, 1900, 2, 1, 0, 0, 0, 0);
diff = datetime_compare(&test_bdatetime, &bdatetime);
ct_test(pTest, diff == 0);
datetime_set_values(&bdatetime, 2013, 6, 6, 23, 59, 59, 0);
datetime_add_minutes(&bdatetime, 60);
datetime_set_values(&test_bdatetime, 2013, 6, 7, 0, 59, 59, 0);
diff = datetime_compare(&test_bdatetime, &bdatetime);
ct_test(pTest, diff == 0);
datetime_set_values(&bdatetime, 2013, 6, 6, 0, 59, 59, 0);
datetime_add_minutes(&bdatetime, -60);
datetime_set_values(&test_bdatetime, 2013, 6, 5, 23, 59, 59, 0);
diff = datetime_compare(&test_bdatetime, &bdatetime);
ct_test(pTest, diff == 0);
}
void testBACnetDateTimeSeconds(
Test * pTest)
{
@@ -886,10 +981,10 @@ void testDateEpoch(
for (year = 1900; year <= 2154; year++) {
for (month = 1; month <= 12; month++) {
for (day = 1; day <= month_days(year, month); day++) {
for (day = 1; day <= datetime_month_days(year, month); day++) {
days = days_since_epoch(year, month, day);
days_since_epoch_into_ymd(days, &test_year, &test_month,
&test_day);
days_since_epoch_into_ymd(days,
&test_year, &test_month, &test_day);
ct_test(pTest, year == test_year);
ct_test(pTest, month == test_month);
ct_test(pTest, day == test_day);
@@ -904,26 +999,26 @@ void testBACnetDayOfWeek(
uint8_t dow = 0;
/* 1/1/1900 is a Monday */
dow = day_of_week(1900, 1, 1);
dow = datetime_day_of_week(1900, 1, 1);
ct_test(pTest, dow == 1);
/* 1/1/2007 is a Monday */
dow = day_of_week(2007, 1, 1);
dow = datetime_day_of_week(2007, 1, 1);
ct_test(pTest, dow == 1);
dow = day_of_week(2007, 1, 2);
dow = datetime_day_of_week(2007, 1, 2);
ct_test(pTest, dow == 2);
dow = day_of_week(2007, 1, 3);
dow = datetime_day_of_week(2007, 1, 3);
ct_test(pTest, dow == 3);
dow = day_of_week(2007, 1, 4);
dow = datetime_day_of_week(2007, 1, 4);
ct_test(pTest, dow == 4);
dow = day_of_week(2007, 1, 5);
dow = datetime_day_of_week(2007, 1, 5);
ct_test(pTest, dow == 5);
dow = day_of_week(2007, 1, 6);
dow = datetime_day_of_week(2007, 1, 6);
ct_test(pTest, dow == 6);
dow = day_of_week(2007, 1, 7);
dow = datetime_day_of_week(2007, 1, 7);
ct_test(pTest, dow == 7);
dow = day_of_week(2007, 1, 31);
dow = datetime_day_of_week(2007, 1, 31);
ct_test(pTest, dow == 3);
}