← Назад к вопросам

Что такое timezone?

2.0 Middle🔥 81 комментариев
#DevOps и инфраструктура#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое timezone?

Timezone (часовой пояс) — это обозначение локального времени относительно UTC (Coordinated Universal Time, универсальное скоординированное время). Это географическое понятие, которое определяет, на сколько часов вперёд или назад местное время отличается от UTC.

Основные концепции

UTC — это стандартное время, выбранное за ноль (нулевой меридиан). На основе UTC вычисляются все остальные часовые пояса:

# UTC на нулевой момент времени
2024-03-23 12:00:00 UTC

# Москва (UTC+3 часа)
2024-03-23 15:00:00 MSK (Moscow Standard Time)

# Нью-Йорк (UTC-5 часов)
2024-03-23 07:00:00 EST (Eastern Standard Time)

# Штат Калифорния (UTC-8 часов)
2024-03-23 04:00:00 PST (Pacific Standard Time)

Timezone в Python

from datetime import datetime, timezone, timedelta
from zoneinfo import ZoneInfo  # Python 3.9+
import pytz  # Старый способ

# Способ 1: Использовать UTC
dt_utc = datetime.now(timezone.utc)
print(dt_utc)  # 2024-03-23 12:00:00+00:00

# Способ 2: Использовать pytz (старый способ)
dt_moscow = datetime.now(pytz.timezone('Europe/Moscow'))
print(dt_moscow)  # 2024-03-23 15:00:00+03:00

# Способ 3: Использовать zoneinfo (новый способ, Python 3.9+)
dt_tokyo = datetime.now(ZoneInfo('Asia/Tokyo'))
print(dt_tokyo)  # 2024-03-23 21:00:00+09:00

# Способ 4: Создать custom timezone
custom_tz = timezone(timedelta(hours=5, minutes=30))
dt_custom = datetime.now(custom_tz)
print(dt_custom)  # 2024-03-23 17:30:00+05:30

Naive vs Aware datetime

Naive datetime — без информации о timezone:

from datetime import datetime

# Naive (без timezone информации)
dt_naive = datetime.now()
print(dt_naive)  # 2024-03-23 12:00:00
print(dt_naive.tzinfo)  # None

# Проблема: непонятно какой это timezone
# 12:00 в Москве? Нью-Йорке? Тайпее?

Aware datetime — с информацией о timezone:

from datetime import datetime, timezone

# Aware (с timezone информацией)
dt_aware = datetime.now(timezone.utc)
print(dt_aware)  # 2024-03-23 12:00:00+00:00
print(dt_aware.tzinfo)  # datetime.timezone.utc

# Всегда ясно: это UTC время

Работа с timezone в Django

# settings.py
USE_TZ = True  # КРИТИЧНО для корректной работы
TIME_ZONE = 'UTC'  # Хранить в БД как UTC

# models.py
from django.db import models
from django.utils import timezone

class BlogPost(models.Model):
    title = models.CharField(max_length=200)
    # Всегда используй DateTimeField с auto_now_add
    created_at = models.DateTimeField(auto_now_add=True)  # Автоматически UTC
    updated_at = models.DateTimeField(auto_now=True)
    
    def time_since_creation(self):
        """Получить время с момента создания"""
        now = timezone.now()  # Всегда UTC-aware
        delta = now - self.created_at
        return delta

# views.py
from django.utils import timezone
from zoneinfo import ZoneInfo

def get_current_time_in_moscow(request):
    # Получить UTC
    now_utc = timezone.now()
    print(f"UTC: {now_utc}")  # 2024-03-23 12:00:00+00:00
    
    # Преобразовать в Москву
    now_moscow = now_utc.astimezone(ZoneInfo('Europe/Moscow'))
    print(f"Moscow: {now_moscow}")  # 2024-03-23 15:00:00+03:00
    
    return now_moscow

# templates/template.html
<!-- Django автоматически форматирует дату в текущий timezone пользователя -->
<p>{{ blog_post.created_at }}</p>
<!-- Результат зависит от TIME_ZONE в settings -->

Конвертирование между timezone

from datetime import datetime
from zoneinfo import ZoneInfo

# Создать дату в UTC
dt_utc = datetime(2024, 3, 23, 12, 0, 0, tzinfo=ZoneInfo('UTC'))
print(f"UTC: {dt_utc}")  # 2024-03-23 12:00:00+00:00

# Конвертировать в разные timezone
dt_moscow = dt_utc.astimezone(ZoneInfo('Europe/Moscow'))
dt_nyc = dt_utc.astimezone(ZoneInfo('America/New_York'))
dt_tokyo = dt_utc.astimezone(ZoneInfo('Asia/Tokyo'))

print(f"Moscow: {dt_moscow}")  # 2024-03-23 15:00:00+03:00
print(f"NYC: {dt_nyc}")  # 2024-03-23 08:00:00-04:00
print(f"Tokyo: {dt_tokyo}")  # 2024-03-23 21:00:00+09:00

# Проверить что это один и тот же момент времени
print(dt_utc == dt_moscow == dt_nyc == dt_tokyo)  # True
print(dt_utc.timestamp())  # 1711181400.0 (одинаков для всех)

DST (Daylight Saving Time)

DST — переход на летнее/зимнее время. Python и pytz/zoneinfo обрабатывают это автоматически:

from zoneinfo import ZoneInfo
from datetime import datetime

# Зимнее время (без DST)
dt_winter = datetime(2024, 1, 15, 12, 0, 0, tzinfo=ZoneInfo('US/Eastern'))
print(f"Winter: {dt_winter}")  # 2024-01-15 12:00:00-05:00 (EST)

# Летнее время (с DST)
dt_summer = datetime(2024, 7, 15, 12, 0, 0, tzinfo=ZoneInfo('US/Eastern'))
print(f"Summer: {dt_summer}")  # 2024-07-15 12:00:00-04:00 (EDT)

# Смещение автоматически изменилось с -5 на -4
print(f"Winter offset: {dt_winter.utcoffset()}")  # -5:00:00
print(f"Summer offset: {dt_summer.utcoffset()}")  # -4:00:00

Типичные ошибки при работе с timezone

# ❌ ОШИБКА 1: Используется naive datetime
from datetime import datetime

dt = datetime.now()  # Naive!
stored_in_db = dt  # Проблема: какой это timezone?

# ✅ ПРАВИЛЬНО: используй aware datetime
from datetime import datetime, timezone

dt = datetime.now(timezone.utc)  # Aware
stored_in_db = dt  # Понятно: это UTC
# ❌ ОШИБКА 2: Преобразование между naive и aware
from datetime import datetime, timezone

dt_naive = datetime.now()
dt_aware = datetime.now(timezone.utc)

# TypeError: can't subtract offset-naive and offset-aware datetimes
# difference = dt_naive - dt_aware

# ✅ ПРАВИЛЬНО: привести к одному типу
dt_naive_utc = datetime.now(timezone.utc).replace(tzinfo=None)  # Remove tzinfo
difference = dt_naive_utc - dt_naive  # Теперь работает
# ❌ ОШИБКА 3: Использовать .replace() вместо .astimezone()
from datetime import datetime, timezone
from zoneinfo import ZoneInfo

dt_utc = datetime(2024, 3, 23, 12, 0, 0, tzinfo=timezone.utc)

# НЕПРАВИЛЬНО: только меняет метаданные
dt_wrong = dt_utc.replace(tzinfo=ZoneInfo('Europe/Moscow'))
print(dt_wrong)  # 2024-03-23 12:00:00+03:00 (НЕПРАВИЛЬНОЕ время!)

# ПРАВИЛЬНО: конвертирует время
dt_correct = dt_utc.astimezone(ZoneInfo('Europe/Moscow'))
print(dt_correct)  # 2024-03-23 15:00:00+03:00 (ПРАВИЛЬНОЕ время)

API для работы с timezone

from zoneinfo import ZoneInfo
from datetime import datetime

# Получить все доступные timezone
from zoneinfo import available_timezones()
print(available_timezones())  # Множество всех timezone

# Проверить валидный ли timezone
try:
    tz = ZoneInfo('Europe/London')
except Exception as e:
    print(f"Invalid timezone: {e}")

# Получить текущее время в разных timezone
def get_current_time_in_cities():
    cities = {
        'Москва': 'Europe/Moscow',
        'Нью-Йорк': 'America/New_York',
        'Лондон': 'Europe/London',
        'Токио': 'Asia/Tokyo',
    }
    
    for city, tz_name in cities.items():
        tz = ZoneInfo(tz_name)
        current_time = datetime.now(tz)
        print(f"{city}: {current_time.strftime('%Y-%m-%d %H:%M:%S %Z')}")

get_current_time_in_cities()

Лучшие практики

  1. Всегда храни время в UTC в базе данных
  2. Конвертируй в локальный timezone только при отображении
  3. Используй aware datetime, никогда naive
  4. Используй zoneinfo в новом коде (Python 3.9+)
  5. Не забывай про DST при работе с историческими данными
  6. Настрой Django: USE_TZ = True, TIME_ZONE = 'UTC'

Вывод

Timezone — это:

  • Локальное время относительно UTC
  • Обозначает смещение от UTC (например, UTC+3)
  • Критичен для корректной работы многоязычных приложений
  • Python предоставляет zoneinfo (3.9+) и pytz для работы
  • Django автоматически обрабатывает timezone при правильной конфигурации
  • Всегда используй aware datetime в production коде
Что такое timezone? | PrepBro