time — funciones relacionadas con el tiempo

El módulo time proporciona funciones para obtener la fecha y hora actuales, medir intervalos de tiempo y crear retardos.

Época de tiempo (Epoch): Las OpenMV Cams basadas en Alif e i.MX RT usan la época POSIX de 1970-01-01 00:00:00 UTC. Las OpenMV Cams basadas en STM32 usan una época de 2000-01-01 00:00:00 UTC. El año de la época puede determinarse en tiempo de ejecución con gmtime(0)[0].

Mantener la fecha/hora de calendario real: Esto requiere un reloj de tiempo real (RTC). En la OpenMV Cam, la hora del sistema la proporciona el objeto machine.RTC. La hora de calendario actual puede establecerse con machine.RTC().datetime(tuple) y se mantiene mediante uno de los siguientes métodos:

  • Una batería de respaldo (un componente opcional en algunas OpenMV Cams).

  • Un protocolo de tiempo en red como ntptime (requiere una conexión de red).

  • Establecerla manualmente en cada encendido. El RTC se mantiene entonces normalmente a través de reinicios suaves, pero se pierde al cortar la alimentación a menos que haya instalada una batería de respaldo.

Si la hora de calendario no se mantiene, las funciones siguientes que hacen referencia a la hora absoluta actual no se comportarán como se espera.

Funciones

time.gmtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]
time.localtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]

Convierte el tiempo secs expresado en segundos desde la Época (ver arriba) en una tupla de 8 elementos que contiene: (year, month, mday, hour, minute, second, weekday, yearday) Si no se proporciona secs o es None, se utiliza la hora actual del RTC.

La función gmtime() devuelve una tupla de fecha y hora en UTC, y localtime() devuelve una tupla de fecha y hora en hora local.

El formato de las entradas de la tupla de 8 elementos es:

  • year incluye el siglo (por ejemplo, 2014).

  • month está entre 1-12

  • mday está entre 1-31

  • hour está entre 0-23

  • minute está entre 0-59

  • second está entre 0-59

  • weekday está entre 0-6 para Lun-Dom

  • yearday está entre 1-366

time.mktime(date_time_tuple: Tuple[int, int, int, int, int, int, int, int]) int

Esta es la función inversa de localtime. Su argumento es una tupla completa de 8 elementos que expresa un tiempo según localtime. Devuelve un entero que es el número de segundos transcurridos desde la época de tiempo.

time.sleep(seconds: float) None

Suspende la ejecución durante el número de segundos indicado. seconds puede ser un número de coma flotante, para suspender durante una fracción de segundo. Para retardos más finos o solo enteros, usa las funciones sleep_ms() y sleep_us().

Llamar a sleep(), incluido sleep(0), garantiza que se llamen las funciones de retorno (callback) pendientes.

time.sleep_ms(ms: int) None

Retarda durante el número de milisegundos indicado, que debe ser positivo o 0.

Esta función retardará durante al menos el número de milisegundos indicado, pero puede tardar más si debe realizarse otro procesamiento, por ejemplo, controladores de interrupción u otros hilos. Pasar 0 para ms aún permitirá que se produzca este otro procesamiento. Usa sleep_us() para retardos más precisos.

Llamar a sleep_ms(), incluido sleep_ms(0), garantiza que se llamen las funciones de retorno (callback) pendientes.

time.sleep_us(us: int) None

Retarda durante el número de microsegundos indicado, que debe ser positivo o 0.

Esta función intenta proporcionar un retardo preciso de al menos us microsegundos, pero puede tardar más si el sistema tiene otro procesamiento de mayor prioridad que realizar.

time.ticks_ms() int

Devuelve un contador de milisegundos creciente con un punto de referencia arbitrario, que se reinicia cíclicamente tras cierto valor.

El valor de reinicio cíclico no se expone explícitamente, pero nos referiremos a él como TICKS_MAX para simplificar la explicación. El periodo de los valores es TICKS_PERIOD = TICKS_MAX + 1. Se garantiza que TICKS_PERIOD es una potencia de dos, pero por lo demás puede diferir de un port a otro. El mismo valor de periodo se usa para todas las funciones ticks_ms(), ticks_us() y ticks_cpu() (por simplicidad). Por tanto, estas funciones devolverán un valor en el rango [0 .. TICKS_MAX], inclusive, con un total de TICKS_PERIOD valores. Ten en cuenta que solo se usan valores no negativos. En su mayor parte, debes tratar los valores devueltos por estas funciones como opacos. Las únicas operaciones disponibles para ellos son las funciones ticks_diff() y ticks_add() descritas a continuación.

Nota: Realizar operaciones matemáticas estándar (+, -) u operadores relacionales (<, <=, >, >=) directamente sobre estos valores producirá resultados no válidos. Realizar operaciones matemáticas y luego pasar sus resultados como argumentos a ticks_diff() o ticks_add() también producirá resultados no válidos de estas últimas funciones.

time.ticks_us() int

Igual que ticks_ms() arriba, pero en microsegundos.

time.ticks_cpu() int

Similar a ticks_ms() y ticks_us(), pero con la mayor resolución posible del sistema. Suele ser el reloj de la CPU, y por eso la función se llama así. Pero no tiene por qué ser un reloj de CPU; en su lugar puede usarse otra fuente de temporización disponible en el sistema (por ejemplo, un temporizador de alta resolución). La unidad de temporización exacta (resolución) de esta función no se especifica a nivel del módulo time, pero la documentación de un port específico puede proporcionar información más concreta. Esta función está pensada para mediciones de rendimiento (benchmarking) muy finas o bucles en tiempo real muy ajustados. Evita usarla en código portable. Está disponible en todas las OpenMV Cams.

time.ticks_add(ticks: int, delta: int) int

Desplaza un valor de ticks en un número dado, que puede ser positivo o negativo. Dado un valor ticks, esta función permite calcular el valor de ticks delta ticks antes o después de él, siguiendo la definición de aritmética modular de los valores de tick (ver ticks_ms() arriba). El parámetro ticks debe ser un resultado directo de una llamada a las funciones ticks_ms(), ticks_us() o ticks_cpu() (o de una llamada previa a ticks_add()). Sin embargo, delta puede ser un número entero arbitrario o una expresión numérica. ticks_add() es útil para calcular plazos límite de eventos/tareas. (Nota: debes usar la función ticks_diff() para trabajar con plazos límite.)

Ejemplos:

# Find out what ticks value there was 100ms ago
print(ticks_add(time.ticks_ms(), -100))

# Calculate deadline for operation and test for it
deadline = ticks_add(time.ticks_ms(), 200)
while ticks_diff(deadline, time.ticks_ms()) > 0:
    do_a_little_of_something()

# Find out TICKS_MAX used by this port
print(ticks_add(0, -1))
time.ticks_diff(ticks1: int, ticks2: int) int

Mide la diferencia de ticks entre los valores devueltos por las funciones ticks_ms(), ticks_us() o ticks_cpu(), como un valor con signo que puede reiniciarse cíclicamente.

El orden de los argumentos es el mismo que para el operador de resta: ticks_diff(ticks1, ticks2) tiene el mismo significado que ticks1 - ticks2. Sin embargo, los valores devueltos por las funciones ticks_ms(), etc. pueden reiniciarse cíclicamente, por lo que usar directamente la resta sobre ellos producirá un resultado incorrecto. Por eso se necesita ticks_diff(), que implementa aritmética modular (o más concretamente, en anillo) para producir un resultado correcto incluso con valores reiniciados cíclicamente (siempre que no estén demasiado distantes entre sí, ver abajo). La función devuelve un valor con signo en el rango [-TICKS_PERIOD/2 .. TICKS_PERIOD/2-1] (esa es una definición de rango típica para enteros binarios con signo en complemento a dos). Si el resultado es negativo, significa que ticks1 ocurrió antes en el tiempo que ticks2. De lo contrario, significa que ticks1 ocurrió después de ticks2. Esto se cumple solo si ticks1 y ticks2 están separados entre sí por no más de TICKS_PERIOD/2-1 ticks. Si eso no se cumple, se devolverá un resultado incorrecto. En concreto, si dos valores de tick están separados por TICKS_PERIOD/2-1 ticks, ese valor será devuelto por la función. Sin embargo, si han transcurrido TICKS_PERIOD/2 ticks de tiempo real entre ellos, la función devolverá -TICKS_PERIOD/2 en su lugar, es decir, el valor del resultado se reiniciará cíclicamente al rango negativo de valores posibles.

Justificación informal de las restricciones anteriores: Supón que estás encerrado en una habitación sin medios para controlar el paso del tiempo salvo un reloj estándar de 12 marcas. Entonces, si miras la esfera ahora y no vuelves a mirar durante otras 13 horas (por ejemplo, si caes en un sueño profundo), cuando finalmente vuelvas a mirar puede parecerte que solo ha pasado 1 hora. Para evitar este error, simplemente mira el reloj con regularidad. Tu aplicación debería hacer lo mismo. La metáfora del «sueño demasiado largo» también se aplica directamente al comportamiento de la aplicación: no dejes que tu aplicación ejecute una sola tarea durante demasiado tiempo. Ejecuta las tareas por pasos y lleva el control del tiempo entre ellos.

ticks_diff() está diseñada para adaptarse a varios patrones de uso, entre ellos:

  • Sondeo (polling) con tiempo de espera. En este caso, el orden de los eventos es conocido, y solo tratarás con resultados positivos de ticks_diff():

    # Wait for GPIO pin to be asserted, but at most 500us
    start = time.ticks_us()
    while pin.value() == 0:
        if time.ticks_diff(time.ticks_us(), start) > 500:
            raise TimeoutError
    
  • Programación de eventos. En este caso, el resultado de ticks_diff() puede ser negativo si un evento está vencido:

    # This code snippet is not optimized
    now = time.ticks_ms()
    scheduled_time = task.scheduled_time()
    if ticks_diff(scheduled_time, now) > 0:
        print("Too early, let's nap")
        sleep_ms(ticks_diff(scheduled_time, now))
        task.run()
    elif ticks_diff(scheduled_time, now) == 0:
        print("Right at time!")
        task.run()
    elif ticks_diff(scheduled_time, now) < 0:
        print("Oops, running late, tell task to run faster!")
        task.run(run_faster=true)
    

Nota: No pases valores de time() a ticks_diff(), debes usar operaciones matemáticas normales sobre ellos. Pero ten en cuenta que time() también puede (y va a) desbordarse. Esto se conoce como https://en.wikipedia.org/wiki/Year_2038_problem .

time.time() int

Devuelve el número de segundos, como entero, transcurridos desde la Época, asumiendo que el RTC subyacente está configurado y mantenido como se describe arriba. Si no hay un RTC configurado, esta función devuelve el número de segundos transcurridos desde un punto de referencia temporal específico del port (para placas embebidas sin un RTC respaldado por batería, normalmente desde el encendido o el reinicio). Si quieres desarrollar una aplicación portable de MicroPython, no deberías confiar en que esta función proporcione una precisión superior al segundo. Si necesitas mayor precisión y marcas de tiempo absolutas, usa time_ns(). Si los tiempos relativos son aceptables, usa las funciones ticks_ms() y ticks_us(). Si necesitas hora de calendario, gmtime() o localtime() sin argumento es una mejor opción.

Diferencia con CPython

En CPython esta función devuelve el número de segundos transcurridos desde la época Unix (1970-01-01 00:00 UTC) como un valor de coma flotante, normalmente con precisión de microsegundos. En la OpenMV Cam devuelve un entero con precisión de un segundo (el hardware no puede representar a la vez un rango temporal amplio y precisión por debajo del segundo en un valor de coma flotante) y la época difiere según la placa (ver Época de tiempo arriba). Sin un RTC respaldado por batería que haya sido configurado, en su lugar cuenta los segundos transcurridos desde el encendido/reinicio.

time.time_ns() int

Similar a time() pero devuelve nanosegundos desde la Época, como entero (normalmente un entero grande, por lo que se asignará en el heap).

Constructores

class time.clock

Devuelve un objeto reloj.

Métodos

tick() None

Comienza a registrar el tiempo transcurrido.

fps() float

Detiene el registro del tiempo transcurrido y devuelve los FPS actuales (fotogramas por segundo).

Llama siempre primero a tick antes de llamar a esta función.

avg() float

Detiene el registro del tiempo transcurrido y devuelve el tiempo medio transcurrido actual en milisegundos.

Llama siempre primero a tick antes de llamar a esta función.

reset() None

Reinicia el objeto reloj.