96 lines
4.1 KiB
C++
Executable File
96 lines
4.1 KiB
C++
Executable File
#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
|