esp32 firmware for a toaster reflow oven WIP!!!!!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
reflower/components/common_utils/src/datetime.c

110 lines
2.9 KiB

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "common_utils/datetime.h"
const char *DT_WKDAY_NAMES[] = {
[MONDAY] = "Mon",
[TUESDAY] = "Tue",
[WEDNESDAY] = "Wed",
[THURSDAY] = "Thu",
[FRIDAY] = "Fri",
[SATURDAY] = "Sat",
[SUNDAY] = "Sun"
};
const char *DT_WKDAY_NAMES_FULL[] = {
[MONDAY] = "Monday",
[TUESDAY] = "Tuesday",
[WEDNESDAY] = "Wednesday",
[THURSDAY] = "Thursday",
[FRIDAY] = "Friday",
[SATURDAY] = "Saturday",
[SUNDAY] = "Sunday"
};
const char *DT_MONTH_NAMES[] = {
[JANUARY] = "Jan",
[FEBRUARY] = "Feb",
[MARCH] = "Mar",
[APRIL] = "Apr",
[MAY] = "May",
[JUNE] = "Jun",
[JULY] = "Jul",
[AUGUST] = "Aug",
[SEPTEMBER] = "Sep",
[OCTOBER] = "Oct",
[NOVEMBER] = "Nov",
[DECEMBER] = "Dec"
};
const char *DT_MONTH_NAMES_FULL[] = {
[JANUARY] = "January",
[FEBRUARY] = "February",
[MARCH] = "March",
[APRIL] = "April",
[MAY] = "May",
[JUNE] = "June",
[JULY] = "July",
[AUGUST] = "August",
[SEPTEMBER] = "September",
[OCTOBER] = "October",
[NOVEMBER] = "November",
[DECEMBER] = "December"
};
static const uint16_t MONTH_LENGTHS[] = { /* 1-based, normal year */
[JANUARY]=31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
_Static_assert(sizeof(MONTH_LENGTHS) / sizeof(uint16_t) == 13, "Months array length");
static const uint16_t MONTH_YEARDAYS[] = { /* 1-based */
[JANUARY]=0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 // // days until 1st of month
};
_Static_assert(sizeof(MONTH_YEARDAYS) / sizeof(uint16_t) == 13, "Months array length");
_Static_assert(MONDAY < SUNDAY, "Weekday ordering");
bool datetime_is_valid(const datetime_t *dt)
{
if (dt == NULL) return false;
// check month first to avoid out-of-bounds read from the MONTH_LENGTHS table
if (!(dt->month >= JANUARY && dt->month <= DECEMBER)) return false;
int monthlen = MONTH_LENGTHS[dt->month];
if (dt->month == FEBRUARY && is_leap_year(dt->year)) {
monthlen = 29;
}
return dt->sec < 60 &&
dt->min < 60 &&
dt->hour < 24 &&
dt->wkday >= MONDAY &&
dt->wkday <= SUNDAY &&
dt->year >= DT_START_YEAR &&
dt->year <= DT_END_YEAR &&
dt->day >= 1 &&
dt->day <= monthlen;
}
bool datetime_set_weekday(datetime_t *dt)
{
dt->wkday = MONDAY; // prevent the validator func erroring out on invalid weekday
if (!datetime_is_valid(dt)) return false;
dt->wkday = date_weekday(dt->year, dt->month, dt->day);
return true;
}
enum weekday date_weekday(uint16_t year, enum month month, uint8_t day)
{
uint16_t days = (DT_START_WKDAY - MONDAY) + (year - DT_START_YEAR) * 365 + MONTH_YEARDAYS[month] + (day - 1);
for (uint16_t i = DT_START_YEAR; i <= year; i++) {
if (is_leap_year(i) && (i < year || month > FEBRUARY)) days++;
}
return MONDAY + days % 7;
}