Fist commit

This commit is contained in:
Angel Ivan
2026-10-02 12:08:21 -06:00
commit 2a9eabce14
54 changed files with 10737 additions and 0 deletions

95
lib/timbre_core/CivilTime.h Executable file
View File

@@ -0,0 +1,95 @@
#pragma once
#include "Model.h"
#include <cstdint>
namespace timbre_core {
struct CivilDateTime {
std::int32_t year = 1970;
std::uint8_t month = 1; // 1..12
std::uint8_t day = 1; // 1..31
std::uint8_t hour = 0; // 0..23
std::uint8_t minute = 0; // 0..59
std::uint8_t second = 0; // 0..59
std::uint8_t weekday = 0; // 0 = Sunday, 6 = Saturday
bool valid() const noexcept;
std::uint16_t minuteOfDay() const noexcept;
std::int64_t dateKey() const noexcept;
std::int64_t minuteSerial() const noexcept;
bool operator==(const CivilDateTime& other) const noexcept;
bool operator!=(const CivilDateTime& other) const noexcept { return !(*this == other); }
};
using CivilDateTimePoint = CivilDateTime;
struct LocalMinuteKey {
std::int64_t date = 0; // YYYYMMDD
std::uint16_t minuteOfDay = 0;
static LocalMinuteKey from(const CivilDateTime& value) noexcept {
return LocalMinuteKey{value.dateKey(), value.minuteOfDay()};
}
std::int64_t serial() const noexcept;
std::int64_t dateKey() const noexcept { return date; }
std::uint16_t minute() const noexcept { return minuteOfDay; }
bool operator==(const LocalMinuteKey& other) const noexcept {
return date == other.date && minuteOfDay == other.minuteOfDay;
}
bool operator!=(const LocalMinuteKey& other) const noexcept { return !(*this == other); }
bool operator<(const LocalMinuteKey& other) const noexcept { return serial() < other.serial(); }
bool operator>(const LocalMinuteKey& other) const noexcept { return serial() > other.serial(); }
bool operator<=(const LocalMinuteKey& other) const noexcept { return serial() <= other.serial(); }
bool operator>=(const LocalMinuteKey& other) const noexcept { return serial() >= other.serial(); }
};
class CivilTime {
public:
// The product deliberately has one fixed civil offset: UTC-06:00.
static constexpr std::int32_t kUtcOffsetSeconds = -6 * 60 * 60;
static constexpr std::int32_t kUtcOffsetMinutes = -6 * 60;
static constexpr std::int32_t UTC_OFFSET_SECONDS = kUtcOffsetSeconds;
static constexpr std::int32_t UTC_OFFSET_MINUTES = kUtcOffsetMinutes;
static bool isLeapYear(std::int32_t year) noexcept;
static std::uint8_t daysInMonth(std::int32_t year, std::uint8_t month) noexcept;
static bool isValidDate(std::int32_t year, std::uint8_t month, std::uint8_t day) noexcept;
static std::uint8_t weekdayForDate(std::int32_t year, std::uint8_t month,
std::uint8_t day) noexcept;
static CivilDateTime fromUnixSeconds(std::int64_t utcSeconds) noexcept;
static bool fromUnixSeconds(std::int64_t utcSeconds, CivilDateTime& result) noexcept;
static CivilDateTime fromUnix(std::int64_t utcSeconds) noexcept {
return fromUnixSeconds(utcSeconds);
}
static bool fromUnix(std::int64_t utcSeconds, CivilDateTime& result) noexcept {
return fromUnixSeconds(utcSeconds, result);
}
static CivilDateTime fromUtc(std::int64_t utcSeconds) noexcept {
return fromUnixSeconds(utcSeconds);
}
static CivilDateTime utcToLocal(std::int64_t utcSeconds) noexcept {
return fromUnixSeconds(utcSeconds);
}
static CivilDateTime fromUnixMilliseconds(std::int64_t utcMilliseconds) noexcept;
static std::int64_t toUnixSeconds(const CivilDateTime& localTime) noexcept;
static bool toUnixSeconds(const CivilDateTime& localTime, std::int64_t& result) noexcept;
static std::int64_t toUnixMilliseconds(const CivilDateTime& localTime) noexcept;
static LocalMinuteKey minuteKey(const CivilDateTime& localTime) noexcept {
return LocalMinuteKey::from(localTime);
}
// These helpers are public because they are useful to a scheduler and are
// deterministic, allocation-free operations on an ESP32.
static std::int64_t daysFromCivil(std::int32_t year, std::uint8_t month,
std::uint8_t day) noexcept;
static bool civilFromDays(std::int64_t days, std::int32_t& year,
std::uint8_t& month, std::uint8_t& day) noexcept;
};
} // namespace timbre_core