// Время в программировании: подводные камни
// Компиляция: zig build-exe time_demo.zig && ./time_demo
// Требует Zig 0.16.0+ (новый std.Io)

const std = @import("std");

pub fn main(init: std.process.Init) !void {
    const io = init.io;

    var buf: [4096]u8 = undefined;
    var out = std.Io.File.stdout().writer(io, &buf);
    const w = &out.interface;

    try w.print("=== Zig: низкоуровневый контроль над временем ===\n\n", .{});

    // 1. Монотонные часы — для измерения длительности
    try w.print("--- 1. Монотонные часы ---\n", .{});
    const start = std.Io.Clock.Timestamp.now(io, .awake);

    var sum: u64 = 0;
    for (0..5_000_000) |i| {
        sum +%= @as(u64, i);
    }

    const elapsed = start.untilNow(io);
    try w.print("Вычисление заняло: {f} ({d} нс)\n", .{ elapsed.raw, elapsed.raw.toNanoseconds() });
    try w.print("Clock `.awake` — это CLOCK_MONOTONIC/CLOCK_UPTIME_RAW.\n", .{});
    try w.print("(sum = {d})\n\n", .{sum});

    // 2. Реальное время (wall clock)
    try w.print("--- 2. Wall clock ---\n", .{});
    const wall = std.Io.Clock.Timestamp.now(io, .real);
    try w.print("Секунд с Unix epoch:     {d}\n", .{wall.raw.toSeconds()});
    try w.print("Наносекунд с Unix epoch: {d}\n", .{wall.raw.toNanoseconds()});
    try w.print("Тип наносекунд — i96: переполнение через ~1.2e21 лет.\n\n", .{});

    // 3. sleep не точен
    try w.print("--- 3. sleep() не точен ---\n", .{});
    try w.print("Запрашиваем 1 мс.\n", .{});
    const sleep_start = std.Io.Clock.Timestamp.now(io, .awake);
    try std.Io.sleep(io, std.Io.Duration.fromMilliseconds(1), .awake);
    const slept = sleep_start.untilNow(io);
    try w.print("Реально прошло: {f} ({d} нс)\n", .{ slept.raw, slept.raw.toNanoseconds() });
    try w.print("sleep гарантирует НЕ МЕНЬШЕ запрошенного, но никогда не ровно.\n\n", .{});

    // 4. Y2038
    try w.print("--- 4. Y2038 ---\n", .{});
    const y2038: i64 = 2_147_483_647;
    try w.print("Граница i32: {d} секунд\n", .{y2038});
    try w.print("= 19 января 2038, 03:14:07 UTC\n", .{});
    try w.print("std.Io.Timestamp хранит наносекунды в i96 — переполнение далеко.\n\n", .{});

    // 5. Разложение Unix timestamp на компоненты даты
    try w.print("--- 5. Разбор Unix timestamp ---\n", .{});
    const epoch_secs: u64 = @intCast(wall.raw.toSeconds());
    const es = std.time.epoch.EpochSeconds{ .secs = epoch_secs };
    const year_day = es.getEpochDay().calculateYearDay();
    const month_day = year_day.calculateMonthDay();
    const day_seconds = es.getDaySeconds();

    try w.print("Сегодня: {d}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2} UTC\n", .{
        year_day.year,
        month_day.month.numeric(),
        @as(u16, month_day.day_index) + 1,
        day_seconds.getHoursIntoDay(),
        day_seconds.getMinutesIntoHour(),
        day_seconds.getSecondsIntoMinute(),
    });
    try w.print("std.time.epoch умеет год, месяц, день; часовые пояса — не из коробки.\n\n", .{});

    try w.print("--- Итог ---\n", .{});
    try w.print("Монотонно → std.Io.Clock.Timestamp.now(io, .awake)\n", .{});
    try w.print("Wall clock → std.Io.Clock.Timestamp.now(io, .real)\n", .{});
    try w.print("Sleep → std.Io.sleep(io, Duration, .awake) — минимум, не максимум\n", .{});
    try w.print("Часовые пояса — нужна внешняя библиотека\n", .{});

    try w.flush();
}
