diff --git a/src/espchrono.cpp b/src/espchrono.cpp index d831884..5633cdd 100644 --- a/src/espchrono.cpp +++ b/src/espchrono.cpp @@ -108,10 +108,12 @@ local_clock::time_point utcToLocal(utc_clock::time_point ts) } namespace { -DateTime toDateTime(seconds32 ts) +DateTime toDateTime(std::chrono::milliseconds ts) { auto _time = ts.count(); + uint8_t millisecond(_time % 1000); + _time /= 1000; // now it is seconds uint8_t second(_time % 60); _time /= 60; // now it is minutes uint8_t minute(_time % 60); @@ -152,10 +154,11 @@ DateTime toDateTime(seconds32 ts) date::day day(_time + 1); // day of month DateTime dateTime{year_month_day{year, month, day}}; - dateTime.hour=hour; - dateTime.minute=minute; - dateTime.second=second; - dateTime.dayOfWeek=dayOfWeek; + dateTime.hour = hour; + dateTime.minute = minute; + dateTime.second = second; + dateTime.millisecond = millisecond; + dateTime.dayOfWeek = dayOfWeek; return dateTime; } } @@ -178,6 +181,7 @@ std::optional parseDateTime(std::string_view str) // both valid: // 2020-11-10T21:31 // 2020-11-10T21:31:10 + // 2020-11-10T21:31:10.001 int year; unsigned month; @@ -185,20 +189,22 @@ std::optional parseDateTime(std::string_view str) uint8_t hour; uint8_t minute; uint8_t second{}; + uint16_t millisecond{}; - constexpr auto dateTimeFormat = "%4d-%2u-%2uT%2hhu:%2hhu:%2hhu"; - if (const auto scanned = std::sscanf(str.data(), dateTimeFormat, &year, &month, &day, &hour, &minute, &second); scanned < 5) + constexpr auto dateTimeFormat = "%4d-%2u-%2uT%2hhu:%2hhu:%2hhu.%3hu"; + if (const auto scanned = std::sscanf(str.data(), dateTimeFormat, &year, &month, &day, &hour, &minute, &second, &millisecond); scanned < 5) return std::nullopt; return DateTime{ .date=date::year_month_day{date::year{year}, date::month{month}, date::day{day}}, .hour=hour, .minute=minute, - .second=second + .second=second, + .millisecond=millisecond }; } -std::optional parseDaypoint(std::string_view str) +std::optional parseDaypoint(std::string_view str) { int8_t hour, minute, second{}; @@ -209,35 +215,35 @@ std::optional parseDaypoint(std::string_view str) if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) return std::nullopt; - return hours32{hour} + minutes32{minute} + seconds32{second}; + return std::chrono::hours{hour} + std::chrono::minutes{minute} + std::chrono::seconds{second}; } std::string toString(const DateTime &dateTime) { - char buf[27]; + char buf[31]; - std::sprintf(buf, "%04i-%02u-%02uT%02hhu:%02hhu:%02hhu", + std::sprintf(buf, "%04i-%02u-%02uT%02hhu:%02hhu:%02hhu.%03hu", int{dateTime.date.year()}, unsigned{dateTime.date.month()}, unsigned{dateTime.date.day()}, - dateTime.hour, dateTime.minute, dateTime.second); + dateTime.hour, dateTime.minute, dateTime.second, dateTime.millisecond); return std::string{buf}; } std::string toString(const LocalDateTime &dateTime) { - char buf[34]; + char buf[35]; date::hh_mm_ss helper{dateTime.timezone.offset + hours32{dateTime.dst ? 1 : 0}}; - std::sprintf(buf, "%04i-%02u-%02uT%02hhu:%02hhu:%02hhu %s%02hhu:%02hhu", + std::sprintf(buf, "%04i-%02u-%02uT%02hhu:%02hhu:%02hhu.%03hu %s%02hhu:%02hhu", int{dateTime.date.year()}, unsigned{dateTime.date.month()}, unsigned{dateTime.date.day()}, - dateTime.hour, dateTime.minute, dateTime.second, + dateTime.hour, dateTime.minute, dateTime.second, dateTime.millisecond, helper.is_negative() ? "-" : "+", uint8_t(helper.hours().count()), uint8_t(helper.minutes().count())); return std::string{buf}; } -std::string toDaypointString(seconds32 seconds) +std::string toDaypointString(std::chrono::seconds seconds) { date::hh_mm_ss helper(seconds); char buf[10]; diff --git a/src/espchrono.h b/src/espchrono.h index 2b76673..2569beb 100644 --- a/src/espchrono.h +++ b/src/espchrono.h @@ -24,7 +24,7 @@ using hours32 = std::chrono::duration>; struct utc_clock { - typedef seconds32 duration; + typedef std::chrono::milliseconds duration; typedef duration::rep rep; typedef duration::period period; typedef std::chrono::time_point time_point; @@ -100,7 +100,7 @@ public: struct local_clock { - typedef seconds32 duration; + typedef std::chrono::milliseconds duration; typedef duration::rep rep; typedef duration::period period; typedef local_time_point time_point; @@ -134,6 +134,7 @@ struct DateTime uint8_t hour{}; uint8_t minute{}; uint8_t second{}; + uint16_t millisecond{}; enum DayOfWeek { Sunday = 1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; DayOfWeek dayOfWeek{}; @@ -144,6 +145,7 @@ struct DateTime hour == other.hour && minute == other.minute && second == other.second && + millisecond == other.millisecond && dayOfWeek == other.dayOfWeek; } }; @@ -173,13 +175,13 @@ LocalDateTime toDateTime(local_clock::time_point ts); std::optional parseDateTime(std::string_view str); //! Returns null if string cannot be parsed -std::optional parseDaypoint(std::string_view str); +std::optional parseDaypoint(std::string_view str); std::string toString(const DateTime &dateTime); std::string toString(const LocalDateTime &dateTime); -std::string toDaypointString(seconds32 seconds); +std::string toDaypointString(std::chrono::seconds seconds); std::chrono::milliseconds ago(millis_clock::time_point a); diff --git a/src/espchrono_impl.cpp b/src/espchrono_impl.cpp index 48d4509..2ce9875 100644 --- a/src/espchrono_impl.cpp +++ b/src/espchrono_impl.cpp @@ -15,8 +15,9 @@ auto espchrono::utc_clock::now() noexcept -> time_point { timeval tv; gettimeofday(&tv, NULL); - seconds32 seconds{tv.tv_sec}; - return time_point{seconds}; + std::chrono::seconds seconds{tv.tv_sec}; + std::chrono::microseconds microseconds{tv.tv_usec}; + return time_point{std::chrono::floor(seconds+microseconds)}; } auto espchrono::millis_clock::now() noexcept -> time_point