32#include "../SensorBuildOpt.h"
33#if !SENSORLIB_EXCLUDE_RTC_COMMON
66 RTC_DateTime() : year(0), month(0), day(0), hour(0), minute(0), second(0), week(0) {}
68 RTC_DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint8_t week = 0) :
69 year(year), month(month), day(day), hour(hour), minute(minute), second(second), week(week) {}
71 RTC_DateTime(
struct tm info) : year(info.tm_year + 1900), month(info.tm_mon + 1), day(info.tm_mday),
72 hour(info.tm_hour), minute(info.tm_min), second(info.tm_sec), week(info.tm_wday) {}
76 if (date ==
nullptr || time ==
nullptr) {
87 year = 2000 + parseStringToUint8(date + 9);
92 else if ( date[2] ==
'n' )
101 month = date[1] ==
'p' ? APRIL : AUGUST;
104 month = date[2] ==
'r' ? MARCH : MAY;
119 day = parseStringToUint8(date + 4);
120 hour = parseStringToUint8(time);
121 minute = parseStringToUint8(time + 3);
122 second = parseStringToUint8(time + 6);
127 return ((d.year == year) && (d.month == month) && (d.day == day)
128 && (d.hour == hour) && (d.minute == minute));
135 t_tm.tm_min = minute;
136 t_tm.tm_sec = second;
137 t_tm.tm_year = year - 1900;
138 t_tm.tm_mon = month - 1;
172 uint8_t parseStringToUint8(
const char *pString)
177 while (
'0' == *pString || *pString ==
' ') {
182 while (
'0' <= *pString && *pString <=
'9') {
184 value += *pString -
'0';
194 RTC_Alarm(
void): second(0), minute(0), hour(0), day(0), week(0) {}
195 RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week ) :
196 second(second), minute(minute), hour(hour), day(day), week(week) {}
231 virtual bool begin(TwoWire &wire,
int sda,
int scl) = 0;
233#elif defined(ESP_PLATFORM)
235#if defined(SENSORLIB_USE_I2C_LEGACY)
250 virtual bool begin(i2c_port_t port_num,
int sda,
int scl) = 0;
263 virtual bool begin(i2c_master_bus_handle_t handle) = 0;
352 uint8_t hour, uint8_t minute, uint8_t second)
374 const char *formatStr = NULL;
375 static char format[FORMAT_BUFFER_SIZE];
381 formatStr =
"%02d:%02d";
384 formatStr =
"%02d:%02d:%02d";
387 formatStr =
"%d-%02d-%02d";
390 formatStr =
"%02d-%02d-%d";
393 formatStr =
"%02d-%02d-%d";
396 formatStr =
"%d-%02d-%02d/%02d:%02d:%02d";
399 formatStr =
"%d-%02d-%02d/%02d:%02d:%02d - %s";
402 formatStr =
"%02d:%02d";
405 int result = formatDateTime(formatStr, format, FORMAT_BUFFER_SIZE, &t);
406 if (result < 0 || (
size_t)result >= FORMAT_BUFFER_SIZE) {
443 if (settimeofday(&val, tz) == -1) {
466 if (localtime_r(&now, &info) == NULL) {
485 if (day < 1 || day > 31 || month < 1 || month > 12) {
493 uint32_t part1 = day;
494 uint32_t part2 = ((month + 1) * 26) / 10;
495 uint32_t part3 = year;
496 uint32_t part4 = year / 4;
497 uint32_t part5 = 6 * (year / 100);
498 uint32_t part6 = year / 400;
500 uint32_t val = (part1 + part2 + part3 + part4 + part5 + part6) % 7;
516 return ((curMonth < 12u) ? (curMonth + 1u) : 1u);
527 return (curYear + 1u);
538 uint32_t isDivisibleBy4 = (year % 4 == 0);
539 uint32_t isDivisibleBy100 = (year % 100 == 0);
540 uint32_t isDivisibleBy400 = (year % 400 == 0);
542 return (isDivisibleBy4 && !isDivisibleBy100) || isDivisibleBy400;
554 constexpr uint8_t DAYS_IN_JANUARY = (31u);
555 constexpr uint8_t DAYS_IN_FEBRUARY = (28u);
556 constexpr uint8_t DAYS_IN_MARCH = (31u);
557 constexpr uint8_t DAYS_IN_APRIL = (30u);
558 constexpr uint8_t DAYS_IN_MAY = (31u);
559 constexpr uint8_t DAYS_IN_JUNE = (30u);
560 constexpr uint8_t DAYS_IN_JULY = (31u);
561 constexpr uint8_t DAYS_IN_AUGUST = (31u);
562 constexpr uint8_t DAYS_IN_SEPTEMBER = (30u);
563 constexpr uint8_t DAYS_IN_OCTOBER = (31u);
564 constexpr uint8_t DAYS_IN_NOVEMBER = (30u);
565 constexpr uint8_t DAYS_IN_DECEMBER = (31u);
567 const uint8_t daysInMonthTable[12] = {DAYS_IN_JANUARY,
581 uint8_t val = daysInMonthTable[month - 1u];
601 void convertUtcToTimezone(
int &year,
int &month,
int &day,
int &hour,
int &minute,
int &second,
int timezoneOffsetSeconds)
603 if (year < 0 || month < 1 || month > 12 || day < 1 || day >
getDaysInMonth(month, year) ||
604 hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
609 int totalSeconds = hour * 3600 + minute * 60 + second;
610 totalSeconds += timezoneOffsetSeconds;
612 int daysOffset = totalSeconds / (24 * 3600);
613 totalSeconds %= (24 * 3600);
615 adjustDate(year, month, day, daysOffset);
617 if (totalSeconds < 0) {
618 totalSeconds += 24 * 3600;
619 adjustDate(year, month, day, -1);
622 hour = totalSeconds / 3600;
623 minute = (totalSeconds % 3600) / 60;
624 second = totalSeconds % 60;
635 int year = utcTime.tm_year + 1900;
636 int month = utcTime.tm_mon + 1;
637 int day = utcTime.tm_mday;
638 int hour = utcTime.tm_hour;
639 int minute = utcTime.tm_min;
640 int second = utcTime.tm_sec;
644 utcTime.tm_year = year - 1900;
645 utcTime.tm_mon = month - 1;
646 utcTime.tm_mday = day;
647 utcTime.tm_hour = hour;
648 utcTime.tm_min = minute;
649 utcTime.tm_sec = second;
659 return ((val >> 4) * 10) + (val & 0x0F);
669 return ((val / 10) << 4) | (val % 10);
674 static const size_t FORMAT_BUFFER_SIZE = 64;
677 void adjustDate(
int &year,
int &month,
int &day,
int daysOffset)
698 int formatDateTime(
const char *fmt,
char *buffer,
size_t bufferSize,
const RTC_DateTime *t)
700 const char *weekString[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thur",
"Fri",
"Sat"};
701 if (!fmt || !buffer || bufferSize == 0 || !t) {
706 t->
getWeek() > 6 ? weekString[0] : weekString[t->getWeek()]);
#define SENSORLIB_LOG_E(...)
uint8_t getMinute() const
uint8_t getSecond() const
RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week)
RTC_DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint8_t week=0)
uint8_t getMinute() const
RTC_DateTime(const char *date, const char *time)
bool operator==(RTC_DateTime d)
RTC_DateTime(struct tm info)
uint8_t getSecond() const
bool(*)(uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, bool writeReg, bool isWrite) CustomCallback
virtual const char * getChipName()=0
Get the name of the RTC chip.
uint32_t getLeapYear(uint32_t year)
Determine whether a given year is a leap year.
uint32_t getDayOfWeek(uint32_t day, uint32_t month, uint32_t year)
Calculate the day of the week for a given date using Zeller's congruence.
virtual void setDateTime(RTC_DateTime datetime)=0
Set the date and time of the RTC using an RTC_DateTime object.
int hwClockWrite()
Write the current system time to the RTC clock chip.
void setDateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
Set the date and time of the RTC using individual values.
static uint8_t BCD2DEC(uint8_t val)
Convert a Binary Coded Decimal (BCD) number to a decimal number.
virtual void reset()
Reset the RTC.
uint8_t getDaysInMonth(uint8_t month, uint16_t year)
Get the number of days in a given month of a specific year, considering leap years.
void convertUtcToTimezone(int &year, int &month, int &day, int &hour, int &minute, int &second, int timezoneOffsetSeconds)
Convert UTC time represented by individual values to the time in the specified timezone.
const char * strftime(DateTimeFormat style=DT_FMT_YMD_HMS_WEEK)
Format the current date and time according to the specified style.
void convertUtcToTimezone(struct tm &utcTime, int timezoneOffsetSeconds)
Overloaded function to convert UTC time represented by a struct tm object to the time in the specifie...
uint16_t getNextYear(uint16_t curYear)
Get the next year based on the current year.
virtual bool begin(SensorCommCustom::CustomCallback callback)=0
Initialize the RTC device using a custom callback.
virtual RTC_DateTime getDateTime()=0
Get the current date and time from the RTC.
time_t hwClockRead(const timezone *tz=NULL)
Read the time from the RTC (Real-Time Clock) and write it to the system clock.
static uint8_t DEC2BCD(uint8_t val)
Convert a decimal number to a Binary Coded Decimal (BCD) number.
uint8_t getNextMonth(uint8_t curMonth)
Get the next month based on the current month.
void getDateTime(struct tm *info)
Retrieve the current date and time from the RTC (Real-Time Clock) and populate a struct tm object.