DateTime¶
Sistema de datetime timezone-aware com configuração plug-and-play. Defina timezone no Settings e tudo é configurado automaticamente.
Configuração Plug-and-Play¶
# src/settings.py
class AppSettings(Settings):
timezone: str = "America/Sao_Paulo" # Timezone padrão
use_tz: bool = True # Usar datetimes aware
datetime_format: str = "%Y-%m-%dT%H:%M:%S%z"
date_format: str = "%Y-%m-%d"
time_format: str = "%H:%M:%S"
Zero configuração explícita: Você NÃO precisa chamar configure_datetime(). O sistema é auto-configurado no startup.
# Verificar se DateTime foi configurado
from strider.config import is_datetime_configured
if is_datetime_configured():
print("DateTime pronto!")
Settings de DateTime¶
| Setting | Tipo | Default | Descrição |
|---|---|---|---|
timezone |
str |
"UTC" |
Timezone padrão da aplicação |
use_tz |
bool |
True |
Usar datetimes aware (com timezone) |
datetime_format |
str |
"%Y-%m-%dT%H:%M:%S%z" |
Formato padrão de datetime |
date_format |
str |
"%Y-%m-%d" |
Formato padrão de data |
time_format |
str |
"%H:%M:%S" |
Formato padrão de hora |
API timezone (Django-style)¶
Tempo Atual¶
from strider.datetime import timezone
# Datetime atual em UTC
now = timezone.now()
# Datetime atual em timezone específico
now_sp = timezone.now("America/Sao_Paulo")
# Datetime UTC (explícito)
utc_now = timezone.utcnow()
# Data atual
today = timezone.today()
Conversão de Timezone¶
from strider.datetime import timezone
dt = timezone.now()
# Converter para timezone
local = timezone.localtime(dt, "America/Sao_Paulo")
# Converter para UTC
utc = timezone.make_aware(naive_dt, "UTC")
Gerenciamento de Timezone¶
from strider.datetime import timezone
# Definir timezone padrão (thread-local)
timezone.activate("America/Sao_Paulo")
# Resetar para UTC
timezone.deactivate()
# Obter timezone atual
tz = timezone.get_current_timezone()
Verificar Aware/Naive¶
from strider.datetime import timezone
timezone.is_aware(dt) # True se tem timezone
timezone.is_naive(dt) # True se não tem timezone
# Tornar aware
aware_dt = timezone.make_aware(naive_dt, "UTC")
# Tornar naive
naive_dt = timezone.make_naive(aware_dt)
Comparações¶
from strider.datetime import timezone
timezone.is_past(dt) # True se antes de agora
timezone.is_future(dt) # True se depois de agora
timezone.is_today(dt) # True se mesmo dia
timezone.is_yesterday(dt) # True se ontem
timezone.is_tomorrow(dt) # True se amanhã
Formatação¶
from strider.datetime import timezone
# Formatar datetime
formatted = timezone.format(dt, "%Y-%m-%d %H:%M:%S")
# Parse de string
dt = timezone.parse("2024-01-15 10:30:00", "%Y-%m-%d %H:%M:%S")
Cálculos¶
from strider.datetime import timezone
# Adicionar tempo
future = timezone.add(dt, days=7, hours=3)
# Subtrair tempo
past = timezone.subtract(dt, days=30)
# Diferença
seconds = timezone.diff(dt1, dt2, unit="seconds")
minutes = timezone.diff(dt1, dt2, unit="minutes")
hours = timezone.diff(dt1, dt2, unit="hours")
days = timezone.diff(dt1, dt2, unit="days")
Helpers de Range¶
from strider.datetime import timezone
# Início/fim do dia
start = timezone.start_of_day(dt)
end = timezone.end_of_day(dt)
# Início/fim do mês
start = timezone.start_of_month(dt)
end = timezone.end_of_month(dt)
# Início/fim do ano
start = timezone.start_of_year(dt)
end = timezone.end_of_year(dt)
Criar DateTime¶
from strider.datetime import timezone
# Criar datetime
dt = timezone.datetime(2024, 1, 15, 10, 30, 0, tz="UTC")
# De timestamp
dt = timezone.from_timestamp(1705315800)
# De string ISO
dt = timezone.from_iso("2024-01-15T10:30:00Z")
Classe DateTime¶
Subclasse customizada de datetime.
from strider.datetime import DateTime
# Criar
dt = DateTime.now()
dt = DateTime.from_timestamp(1705315800)
dt = DateTime.from_iso("2024-01-15T10:30:00Z")
# Converter
dt.to_timezone("America/Sao_Paulo")
dt.to_utc()
dt.to_iso()
dt.to_timestamp()
Em Models¶
Auto Timestamps¶
from strider import Model, Field
from strider.datetime import DateTime
from sqlalchemy.orm import Mapped
class Post(Model):
__tablename__ = "posts"
# Definido apenas no INSERT
created_at: Mapped[DateTime] = Field.datetime(auto_now_add=True)
# Definido no INSERT e UPDATE
updated_at: Mapped[DateTime] = Field.datetime(auto_now=True)
# Datetime opcional
published_at: Mapped[DateTime | None] = Field.datetime(nullable=True)
Armazenamento¶
Todos os datetimes são armazenados em UTC:
| Banco | Tipo |
|---|---|
| PostgreSQL | TIMESTAMP WITH TIME ZONE |
| SQLite | DATETIME |
| MySQL | DATETIME |
Queries¶
from strider.datetime import timezone
# Filtrar por data
posts = await Post.objects.using(db).filter(
created_at__gte=timezone.start_of_day(),
created_at__lt=timezone.end_of_day(),
).all()
# Filtrar por range
start = timezone.datetime(2024, 1, 1)
end = timezone.datetime(2024, 12, 31)
posts = await Post.objects.using(db).filter(
created_at__range=(start, end)
).all()
Funções Standalone¶
from strider.datetime import (
now,
utcnow,
today,
make_aware,
make_naive,
is_aware,
is_naive,
format_datetime,
parse_datetime,
add_days,
add_hours,
diff_days,
start_of_day,
end_of_day,
)
# Uso
current = now()
formatted = format_datetime(current, "%Y-%m-%d")
tomorrow = add_days(current, 1)
Nomes de Timezone¶
Formatos suportados:
# Nomes padrão
timezone.now("UTC")
timezone.now("America/Sao_Paulo")
timezone.now("Europe/London")
# Strings de offset
timezone.now("+03:00")
timezone.now("-05:00")
Boas Práticas¶
1. Sempre use UTC para armazenamento¶
# Bom
created_at = timezone.now() # UTC
# Ruim
created_at = datetime.now() # Hora local
2. Converta apenas para exibição¶
# Armazene em UTC
post.created_at = timezone.now()
# Converta para exibição ao usuário
local_time = timezone.localtime(post.created_at, user.timezone)
3. Use auto timestamps¶
# Bom
created_at: Mapped[DateTime] = Field.datetime(auto_now_add=True)
# Evite definição manual
4. Sempre use datetimes aware¶
# Bom
dt = timezone.now()
# Ruim
dt = datetime.utcnow() # Datetime naive