// Время в программировании: подводные камни
// Запуск: go run time_demo.go

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println("=== Go: монотонные часы, часовые пояса и ловушки ===")
	fmt.Println()

	// 1. time.Now() содержит и wall clock, и monotonic clock
	fmt.Println("--- 1. Два часовых механизма в одном time.Time ---")
	now := time.Now()
	fmt.Printf("time.Now() = %v\n", now)
	fmt.Println("Внутри time.Time хранятся ДВА значения:")
	fmt.Println("  - wall clock (для отображения)")
	fmt.Println("  - monotonic reading (для вычисления разницы)")
	fmt.Println()

	// 2. time.Since() использует монотонные часы автоматически
	fmt.Println("--- 2. Измерение длительности ---")
	start := time.Now()
	sum := uint64(0)
	for i := uint64(0); i < 5_000_000; i++ {
		sum += i
	}
	elapsed := time.Since(start) // использует monotonic reading
	fmt.Printf("Вычисление заняло: %v\n", elapsed)
	fmt.Printf("time.Since() безопасен — не зависит от NTP.\n")
	fmt.Printf("(sum = %d)\n\n", sum)

	// 3. Ловушка: time.Parse() отбрасывает монотонные часы
	fmt.Println("--- 3. Ловушка с time.Parse ---")
	// Go использует магическую дату-образец: Mon Jan 2 15:04:05 MST 2006
	// Это 01/02 03:04:05 PM '06 -0700 — каждая цифра по порядку
	parsed, err := time.Parse("2006-01-02 15:04:05", "2038-01-19 03:14:07")
	if err != nil {
		fmt.Println("Ошибка:", err)
	} else {
		fmt.Printf("Parsed: %v\n", parsed)
		fmt.Println("Дата-образец в Go: Mon Jan 2 15:04:05 MST 2006")
		fmt.Println("Каждое число уникально: 01/02 03:04:05 '06 -0700")
	}
	fmt.Println()

	// 4. Часовые пояса: одно и то же время — разные строки
	fmt.Println("--- 4. Часовые пояса ---")
	utc := time.Date(2038, 1, 19, 3, 14, 7, 0, time.UTC)
	moscow, _ := time.LoadLocation("Europe/Moscow")
	tokyo, _ := time.LoadLocation("Asia/Tokyo")
	samoa, _ := time.LoadLocation("Pacific/Apia")

	fmt.Printf("UTC:    %s\n", utc.In(time.UTC).Format(time.RFC3339))
	if moscow != nil {
		fmt.Printf("Москва: %s\n", utc.In(moscow).Format(time.RFC3339))
	}
	if tokyo != nil {
		fmt.Printf("Токио:  %s\n", utc.In(tokyo).Format(time.RFC3339))
	}
	if samoa != nil {
		fmt.Printf("Самоа:  %s\n", utc.In(samoa).Format(time.RFC3339))
	}
	fmt.Println("Одно мгновение — четыре разных строки.")
	fmt.Println()

	// 5. Y2038 в Go
	fmt.Println("--- 5. Y2038 ---")
	y2038 := time.Unix(2_147_483_647, 0)
	fmt.Printf("i32::MAX секунд с epoch = %s\n", y2038.UTC().Format(time.RFC3339))
	fmt.Println("Go хранит время в int64 наносекундах от epoch.")
	fmt.Println("Диапазон: примерно 1678–2262 годы.")
	fmt.Println("Y2038 для int32 не грозит, но int64 наносекунд кончится в 2262.")
	fmt.Println()

	// 6. Сравнение: Equal() vs ==
	fmt.Println("--- 6. Сравнение времени ---")
	t1 := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
	loc, _ := time.LoadLocation("Europe/London")
	var t2 time.Time
	if loc != nil {
		t2 = time.Date(2025, 1, 1, 0, 0, 0, 0, loc)
	} else {
		t2 = t1
	}
	fmt.Printf("t1 (UTC) == t2 (London): %v (оператор ==)\n", t1 == t2)
	fmt.Printf("t1.Equal(t2):            %v (метод Equal)\n", t1.Equal(t2))
	fmt.Println("== сравнивает структуры побайтово (включая Location).")
	fmt.Println("Equal() сравнивает мгновения во времени.")
	fmt.Println()

	fmt.Println("--- Итог ---")
	fmt.Println("time.Now() хранит wall + monotonic автоматически")
	fmt.Println("time.Since() безопасен для измерения длительности")
	fmt.Println("time.Parse() дата-образец: 2006-01-02 15:04:05")
	fmt.Println("Для сравнения времени — Equal(), не ==")
	fmt.Println("Go наносекунды в int64 кончатся в 2262 году")
}
