How to get current non-buggy time? (millis_64())

I’m trying to obtain the current timestamp at a specific time t1, and check for its validity later at t2 by making sure t2-t1<max_delay.

I know of millis(), but I want a more reasonable version that won’t do crazy things like wraparound on the int32 and consider my things “recent” after 49.7 days because of the overflow.

Something like in the scheduler, using an int64: Blaming esphome/esphome/core/scheduler.cpp at d3592c451bc8570419126c8d753ec05ff5c8d55e · esphome/esphome · GitHub

How do I get access to this? (Currently that method of the scheduler is private, so I can’t access it via App.scheduler.millis_().)

Thanks

The scheduler’s internal 64-bit timer is kept private because it’s optimized for the scheduler’s specific performance and memory constraints. For general time tracking in components, there are better alternatives that don’t require modifying the core scheduler.

You could use std::chrono::steady_clock for overflow-safe time tracking. It’s part of the C++ standard library and handles 64-bit timestamps automatically.

Example:

#include <chrono>

// Store a time point
std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();

// Later, check elapsed time
auto now = std::chrono::steady_clock::now();
auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();

This avoids the 32-bit millis() overflow issue entirely. ESPHome already uses this pattern in some components (like the Haier climate component).

Reference: Date and time library - cppreference.com

2 Likes

Hey there,
I tried this, but it wont compile.
Guess its because I have to use esp-idf because I am developing for an esp32-h2.

So, can anyone tell me, how to to this (measure the time it takes to do something in millis without rollover-problems) using ESPHome and the esp-idf instead of Arduino/cpp?

You’ll need to be more specific about what you are trying to do exactly. This page has some good information in it about using the IDF timer:
ESP-IDF equivalent of Arduino millis() | TechOverflow

something like this could work

#include <esp_timer.h>

uint64_t millis64() {
    return esp_timer_get_time() / 1000;
}

esphome has this definition

uint32_t IRAM_ATTR HOT millis() { return (uint32_t) (esp_timer_get_time() / 1000ULL); }

This uses the underlying esp32 timer function but strips it down to 32 bits overflow. 32 bits of milliseconds is over a month. Unless you need to measure periods of time longer than that, you should be fine using unsigned calculations (they handle the overflow just fine). But, if your start time can be more than a month earlier than the latest you will need to check, you will need to use more than 32 bits and can use the millis64() listed above (or just leave it in microseconds)