forked from electro/esp-irblaster
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.
132 lines
3.0 KiB
132 lines
3.0 KiB
3 years ago
|
/**
|
||
|
* TODO file description
|
||
|
*
|
||
|
* Created on 2019/09/13.
|
||
|
*/
|
||
|
|
||
|
#ifndef CSPEMU_DATETIME_H
|
||
|
#define CSPEMU_DATETIME_H
|
||
|
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
|
||
|
enum weekday {
|
||
|
MONDAY = 1,
|
||
|
TUESDAY,
|
||
|
WEDNESDAY,
|
||
|
THURSDAY,
|
||
|
FRIDAY,
|
||
|
SATURDAY,
|
||
|
SUNDAY
|
||
|
};
|
||
|
_Static_assert(MONDAY==1, "enum weekday numbering Mon");
|
||
|
_Static_assert(SUNDAY==7, "enum weekday numbering Sun");
|
||
|
|
||
|
enum month {
|
||
|
JANUARY = 1,
|
||
|
FEBRUARY,
|
||
|
MARCH,
|
||
|
APRIL,
|
||
|
MAY,
|
||
|
JUNE,
|
||
|
JULY,
|
||
|
AUGUST,
|
||
|
SEPTEMBER,
|
||
|
OCTOBER,
|
||
|
NOVEMBER,
|
||
|
DECEMBER
|
||
|
};
|
||
|
_Static_assert(JANUARY==1, "enum month numbering Jan");
|
||
|
_Static_assert(DECEMBER==12, "enum month numbering Dec");
|
||
|
|
||
|
/** Abbreviated weekday names */
|
||
|
extern const char *DT_WKDAY_NAMES[];
|
||
|
/** Full-length weekday names */
|
||
|
extern const char *DT_WKDAY_NAMES_FULL[];
|
||
|
/** Abbreviated month names */
|
||
|
extern const char *DT_MONTH_NAMES[];
|
||
|
/** Full-length month names */
|
||
|
extern const char *DT_MONTH_NAMES_FULL[];
|
||
|
|
||
|
typedef struct datetime {
|
||
|
uint16_t year;
|
||
|
enum month month;
|
||
|
uint8_t day;
|
||
|
uint8_t hour;
|
||
|
uint8_t min;
|
||
|
uint8_t sec;
|
||
|
enum weekday wkday; // 1=monday
|
||
|
} datetime_t;
|
||
|
|
||
|
// Templates for printf
|
||
|
#define DT_FORMAT_DATE "%d/%d/%d"
|
||
|
#define DT_SUBS_DATE(dt) (dt).year, (dt).month, (dt).day
|
||
|
|
||
|
#define DT_FORMAT_TIME "%d:%02d:%02d"
|
||
|
#define DT_SUBS_TIME(dt) (dt).hour, (dt).min, (dt).sec
|
||
|
|
||
|
#define DT_FORMAT_DATE_WK DT_FORMAT_WK " " DT_FORMAT_DATE
|
||
|
#define DT_SUBS_DATE_WK(dt) DT_SUBS_WK(dt), DT_SUBS_DATE(dt)
|
||
|
|
||
|
#define DT_FORMAT_WK "%s"
|
||
|
#define DT_SUBS_WK(dt) DT_WKDAY_NAMES[(dt).wkday]
|
||
|
|
||
|
#define DT_FORMAT_DATE_TIME DT_FORMAT_DATE " " DT_FORMAT_TIME
|
||
|
#define DT_SUBS_DATE_TIME(dt) DT_SUBS_DATE(dt), DT_SUBS_TIME(dt)
|
||
|
|
||
|
#define DT_FORMAT DT_FORMAT_DATE_WK " " DT_FORMAT_TIME
|
||
|
#define DT_SUBS(dt) DT_SUBS_DATE_WK(dt), DT_SUBS_TIME(dt)
|
||
|
|
||
|
// base century for two-digit year conversions
|
||
|
#define DT_CENTURY 2000
|
||
|
// start year for weekday computation
|
||
|
#define DT_START_YEAR 2019
|
||
|
// January 1st weekday of DT_START_YEAR
|
||
|
#define DT_START_WKDAY TUESDAY
|
||
|
// max date supported by 2-digit year RTC counters (it can't check Y%400==0 with only two digits)
|
||
|
#define DT_END_YEAR 2399
|
||
|
|
||
|
typedef union __attribute__((packed)) {
|
||
|
struct __attribute__((packed)) {
|
||
|
uint8_t ones : 4;
|
||
|
uint8_t tens : 4;
|
||
|
};
|
||
|
uint8_t byte;
|
||
|
} bcd_t;
|
||
|
_Static_assert(sizeof(bcd_t) == 1, "Bad bcd_t len");
|
||
|
|
||
|
/** Check if a year is leap */
|
||
|
static inline bool is_leap_year(int year)
|
||
|
{
|
||
|
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if a datetime could be valid (ignores leap years)
|
||
|
*
|
||
|
* @param[in] dt
|
||
|
* @return basic validations passed
|
||
|
*/
|
||
|
bool datetime_is_valid(const datetime_t *dt);
|
||
|
|
||
|
/**
|
||
|
* Set weekday based on a date in a given datetime
|
||
|
*
|
||
|
* @param[in,out] dt
|
||
|
* @return success
|
||
|
*/
|
||
|
bool datetime_set_weekday(datetime_t *dt);
|
||
|
|
||
|
/**
|
||
|
* Get weekday for given a date
|
||
|
*
|
||
|
* @param year - year number
|
||
|
* @param month - 1-based month number
|
||
|
* @param day - 1-based day number
|
||
|
* @return weekday
|
||
|
*/
|
||
|
enum weekday date_weekday(uint16_t year, enum month month, uint8_t day);
|
||
|
|
||
|
|
||
|
#endif //CSPEMU_DATETIME_H
|