<===
2026-02-16 10:33:48
# Простая логика времени для Украины под CircuitPython.
# Вход: UTC-дата/время (обычно из GPS)
# Выход: локальное время (часы, минуты, секунды) и флаг летнего времени.
def is_leap_year(year):
# Год високосный?
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
def days_in_month(year, month):
# Количество дней в месяце
if month == 2:
return 29 if is_leap_year(year) else 28
if month in (1, 3, 5, 7, 8, 10, 12):
return 31
return 30
def date_to_ordinal(year, month, day):
# Переводим дату в "номер дня" с 0001‑01‑01 (как в datetime.toordinal)
# Чтобы можно было узнать день недели.
# 0001‑01‑01 считаем днём 1.
n = day
for m in range(1, month):
n += days_in_month(year, m)
# Грубая формула количества дней в предыдущих годах:
# year - 1 полных лет
y = year - 1
n += y * 365 + y // 4 - y // 100 + y // 400
return n
def weekday(year, month, day):
# День недели: 0=понедельник, ..., 6=воскресенье
# В Python datetime.toordinal().weekday() даёт ровно это.
ord_day = date_to_ordinal(year, month, day)
return (ord_day - 1) % 7
def last_sunday(year, month):
# Находим последнюю воскресенье в месяце
d = days_in_month(year, month)
while weekday(year, month, d) != 6: # 6 = воскресенье
d -= 1
return d
def is_summer_time_ukraine(year, month, day, hour, minute, second):
"""
Возвращает True, если в Украине действовало летнее время (UTC+3),
и False — если зимнее (UTC+2).
Правило:
- до конца 2024 года включительно: стандарт Европа (последнее воскресенье марта/октября);[web:25][web:34][web:22]
- с 2025 года и далее летнего времени НЕТ (всегда UTC+2).[web:14][web:15][web:17][web:36]
"""
# С 2025 года Украина остаётся на постоянном UTC+2, без летнего времени.
if year >= 2025:
return False
# Переходы до отмены:
# начало DST: последняя воскресенье марта в 03:00 по UTC (подгоняем под обычные EU‑правила)
# конец DST: последняя воскресенье октября в 04:00 по UTC (примерно так для EET/EEST).[web:25][web:34]
# найдём даты переходов для этого года
start_day = last_sunday(year, 3)
end_day = last_sunday(year, 10)
# Сравниваем "момент времени" по UTC с точками перехода.
# Приведём всё к кортежу (month, day, hour, minute, second) для сравнения.
current = (month, day, hour, minute, second)
start = (3, start_day, 3, 0, 0) # 03:00 в марте
end = (10, end_day, 4, 0, 0) # 04:00 в октябре
# Летнее время действует между start (включительно) и end (исключая end).
return current >= start and current < end
def utc_to_kyiv(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_second):
"""
Переводит UTC в киевское время.
Возвращает (year, month, day, hour, minute, second, is_summer).
is_summer = True -> летнее время (UTC+3)
is_summer = False -> зимнее время (UTC+2)
"""
is_summer = is_summer_time_ukraine(
utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_second
)
offset_hours = 3 if is_summer else 2
# Добавляем сдвиг к UTC
total_seconds = utc_hour * 3600 + utc_minute * 60 + utc_second
total_seconds += offset_hours * 3600
# Нормализуем день/дату
# Шаг 1: сдвиг по дням
extra_days = 0
while total_seconds >= 24 * 3600:
total_seconds -= 24 * 3600
extra_days += 1
while total_seconds < 0:
total_seconds += 24 * 3600
extra_days -= 1
# Шаг 2: добавляем extra_days к дате
year = utc_year
month = utc_month
day = utc_day
# вперёд
while extra_days > 0:
dim = days_in_month(year, month)
if day < dim:
day += 1
extra_days -= 1
else:
day = 1
month += 1
if month > 12:
month = 1
year += 1
extra_days -= 1
# назад
while extra_days < 0:
if day > 1:
day -= 1
extra_days += 1
else:
month -= 1
if month < 1:
month = 12
year -= 1
day = days_in_month(year, month)
extra_days += 1
# Разбираем обратно время
hour = total_seconds // 3600
minute = (total_seconds % 3600) // 60
second = total_seconds % 60
return year, month, day, hour, minute, second, is_summer
# -------------------------------
# Пример использования с GPS‑UTC
# -------------------------------
def gps_utc_to_kyiv(date_str, time_str):
"""
date_str: 'DDMMYY' или 'YYYYMMDD' — подстрой под свой формат
time_str: 'HHMMSS'
Тут пример для формата NMEA GPRMC: DDMMYY и HHMMSS.
"""
# Разбор NMEA‑формата DDMMYY
# ВНИМАНИЕ: подстрой под то, что у тебя реально в коде!
day = int(date_str[0:2])
month = int(date_str[2:4])
year = 2000 + int(date_str[4:6]) # NMEA даёт год как 2 цифры
hour = int(time_str[0:2])
minute = int(time_str[2:4])
second = int(time_str[4:6])
return utc_to_kyiv(year, month, day, hour, minute, second)
# Если хочешь просто сейчас:
if __name__ == "__main__":
# пример: UTC 27.10.2024 00:30:00 (ещё лето, перед переводом)
y, m, d, hh, mm, ss, summer = utc_to_kyiv(2024, 10, 27, 0, 30, 0)
print("Kyiv:", y, m, d, hh, mm, ss, "summer:", summer)
Back to list