Como Trabalhar com Tempo e Timestamps em Zig

Introdução

Trabalhar com tempo é essencial para logs, medição de performance, timestamps em dados, timeouts e agendamento de tarefas. Zig oferece std.time com funções precisas para medição de tempo e obtenção de timestamps.

Nesta receita, você aprenderá a obter o tempo atual, medir duração de operações e formatar timestamps.

Pré-requisitos

Obter Timestamp Atual

const std = @import("std");

pub fn main() !void {
    // Timestamp Unix (segundos desde 1970-01-01)
    const ts = std.time.timestamp();
    std.debug.print("Timestamp Unix: {d}\n", .{ts});

    // Timestamp em milissegundos
    const ms = std.time.milliTimestamp();
    std.debug.print("Milissegundos: {d}\n", .{ms});

    // Timestamp em nanossegundos (alta resolução)
    const ns = std.time.nanoTimestamp();
    std.debug.print("Nanossegundos: {d}\n", .{ns});
}

Medir Tempo de Execução

const std = @import("std");

pub fn main() !void {
    // Usar Timer para medir duração
    var timer = try std.time.Timer.start();

    // Simular trabalho
    var soma: u64 = 0;
    for (0..10_000_000) |i| {
        soma += i;
    }

    const elapsed = timer.read();
    const ms = @as(f64, @floatFromInt(elapsed)) / std.time.ns_per_ms;
    const us = @as(f64, @floatFromInt(elapsed)) / std.time.ns_per_us;

    std.debug.print("Soma: {d}\n", .{soma});
    std.debug.print("Tempo: {d:.3} ms ({d:.1} us)\n", .{ ms, us });
    std.debug.print("Tempo (ns): {d}\n", .{elapsed});
}

Converter Timestamp para Componentes de Data

const std = @import("std");

const DataHora = struct {
    ano: u16,
    mes: u8,
    dia: u8,
    hora: u8,
    minuto: u8,
    segundo: u8,
};

fn timestampParaData(timestamp: i64) DataHora {
    const epoch = std.time.epoch.EpochSeconds{ .secs = @intCast(timestamp) };
    const dia_epoch = epoch.getEpochDay();
    const ano_dia = dia_epoch.calculateYearDay();
    const mes_dia = ano_dia.calculateMonthDay();
    const dia_seg = epoch.getDaySeconds();

    return .{
        .ano = ano_dia.year,
        .mes = mes_dia.month.numeric(),
        .dia = mes_dia.day_index + 1,
        .hora = dia_seg.getHoursIntoDay(),
        .minuto = dia_seg.getMinutesIntoHour(),
        .segundo = dia_seg.getSecondsIntoMinute(),
    };
}

pub fn main() !void {
    const ts = std.time.timestamp();
    const dt = timestampParaData(ts);

    std.debug.print("Data/Hora UTC: {d:0>4}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2}\n", .{
        dt.ano, dt.mes, dt.dia,
        dt.hora, dt.minuto, dt.segundo,
    });

    // Timestamp conhecido: 2026-01-01 00:00:00 UTC
    const ts_2026 = timestampParaData(1767225600);
    std.debug.print("2026-01-01: {d:0>4}-{d:0>2}-{d:0>2}\n", .{
        ts_2026.ano, ts_2026.mes, ts_2026.dia,
    });
}

Comparar Tempos (Benchmarking)

const std = @import("std");

fn somaIterativa(n: u64) u64 {
    var soma: u64 = 0;
    var i: u64 = 0;
    while (i <= n) : (i += 1) {
        soma += i;
    }
    return soma;
}

fn somaFormula(n: u64) u64 {
    return n * (n + 1) / 2;
}

pub fn main() !void {
    const n: u64 = 100_000_000;

    // Medir soma iterativa
    var timer1 = try std.time.Timer.start();
    const r1 = somaIterativa(n);
    const t1 = timer1.read();

    // Medir soma por fórmula
    var timer2 = try std.time.Timer.start();
    const r2 = somaFormula(n);
    const t2 = timer2.read();

    const t1_ms = @as(f64, @floatFromInt(t1)) / std.time.ns_per_ms;
    const t2_ms = @as(f64, @floatFromInt(t2)) / std.time.ns_per_ms;

    std.debug.print("Soma iterativa: {d} ({d:.3} ms)\n", .{ r1, t1_ms });
    std.debug.print("Soma fórmula:   {d} ({d:.3} ms)\n", .{ r2, t2_ms });
    std.debug.print("Resultados iguais: {}\n", .{r1 == r2});

    if (t1 > 0 and t2 > 0) {
        std.debug.print("Fórmula é {d:.0}x mais rápida\n", .{
            @as(f64, @floatFromInt(t1)) / @as(f64, @floatFromInt(t2)),
        });
    }
}

Constantes de Tempo Úteis

const std = @import("std");

pub fn main() !void {
    std.debug.print("Constantes de tempo em Zig (std.time):\n\n", .{});

    std.debug.print("ns_per_us  = {d} (nanosegundos por microssegundo)\n", .{std.time.ns_per_us});
    std.debug.print("ns_per_ms  = {d} (nanosegundos por milissegundo)\n", .{std.time.ns_per_ms});
    std.debug.print("ns_per_s   = {d} (nanosegundos por segundo)\n", .{std.time.ns_per_s});
    std.debug.print("ns_per_min = {d} (nanosegundos por minuto)\n", .{std.time.ns_per_min});
    std.debug.print("s_per_min  = {d} (segundos por minuto)\n", .{std.time.s_per_min});
    std.debug.print("s_per_hour = {d} (segundos por hora)\n", .{std.time.s_per_hour});
    std.debug.print("s_per_day  = {d} (segundos por dia)\n", .{std.time.s_per_day});
}

Dicas e Boas Práticas

  1. Use Timer para benchmarks: Mais preciso que calcular diferenças de timestamp.

  2. nanoTimestamp para alta resolução: Quando milissegundos não são suficientes.

  3. Timestamps são UTC: Ajuste para fuso horário local quando necessário.

  4. Cuidado com benchmarks em debug: Compile com zig build -Doptimize=ReleaseFast para benchmarks realistas.

Receitas Relacionadas

Tutoriais Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.