Mam pole uwzględniające strefę czasową timestamptz
w PostgreSQL. Kiedy pobieram dane z tabeli, chcę odjąć teraz czas, aby uzyskać jego wiek.
Problem mam jest to, że zarówno datetime.datetime.now()
i datetime.datetime.utcnow()
wydają się powrócić strefy czasowej nieświadomych znaczniki czasu, co powoduje mi się następujący błąd:
TypeError: can't subtract offset-naive and offset-aware datetimes
Czy istnieje sposób, aby tego uniknąć (najlepiej bez użycia modułu innej firmy).
EDYCJA: Dzięki za sugestie, jednak próba dostosowania strefy czasowej wydaje się dawać błędy. Więc po prostu użyję strefy czasowej nieświadomej znaczników czasowych w PG i zawsze wstawiam używając:
NOW() AT TIME ZONE 'UTC'
W ten sposób wszystkie moje znaczniki czasu są domyślnie UTC (chociaż jest to bardziej denerwujące).
datetime.timezone.utc
lubpytz.utc
. Na przykład,1970-01-01 00:00:00
jest niejednoznaczne i trzeba dodać strefę czasową disambiguate:1970-01-01 00:00:00 UTC
. Widzisz, musisz dodać nowe informacje; znacznik czasu sam w sobie jest niejednoznaczny.utcnow
nie powinno zwracać naiwnego obiektu lub znacznika czasu bez strefy czasowej. Z dokumentów „Świadomy obiekt służy do przedstawienia określonego momentu w czasie, który nie jest otwarty na interpretację”. Każda godzina w UTC spełnia z definicji to kryterium.Prawidłowym rozwiązaniem jest dodanie informacji o strefie czasowej, np. Aby uzyskać bieżący czas jako świadomy obiekt daty i godziny w Pythonie 3:
W starszych wersjach Pythona możesz sam zdefiniować
utc
obiekt tzinfo (przykład z dokumentów datetime):następnie:
źródło
Wiem, że niektórzy ludzie używają Django specjalnie jako interfejsu do abstrakcji tego typu interakcji z bazą danych. Django zapewnia narzędzia, których można użyć do tego:
Musisz skonfigurować podstawową infrastrukturę ustawień Django, nawet jeśli tylko używasz tego typu interfejsu (w ustawieniach musisz uwzględnić,
USE_TZ=True
aby uzyskać świadomą datę i godzinę).Samo to prawdopodobnie nie jest wystarczająco blisko, aby zmotywować cię do używania Django jako interfejsu, ale istnieje wiele innych korzyści. Z drugiej strony, jeśli natknąłeś się tutaj, ponieważ manipulowałeś aplikacją Django (tak jak ja), to może to pomaga ...
źródło
USE_TZ=True
, aby uzyskać świadomą datę i godzinę.+ timedelta(hours=5, minutes=30)
ISTJest to bardzo proste i przejrzyste rozwiązanie
Dwie linie kodu
Wniosek: musisz zarządzać zmiennymi datetime przy użyciu tych samych informacji o czasie
źródło
diff = datetime.now(timezone.utc) - your_timezone_aware_variable
działa (a(a - b)
powyższy wzór wyjaśnia, dlaczego(a - b)
może działać, nawet jeślia.tzinfo
nie jestb.tzinfo
).Moduł psycopg2 ma własne definicje stref czasowych, więc skończyłem pisać własne opakowanie wokół utcnow:
i używaj
pg_utcnow
tylko wtedy, gdy potrzebujesz aktualnego czasu, aby porównać z PostgreSQLtimestamptz
źródło
Też napotkałem ten sam problem. Potem znalazłem rozwiązanie po wielu poszukiwaniach.
Problem polegał na tym, że kiedy pobieramy obiekt datetime z modelu lub formy, jest on rozpoznawany z przesunięciem, a jeśli otrzymujemy czas przez system, jest naiwny .
Więc zrobiłem to, że mam aktualny czas za pomocą timezone.now () i zaimportuję strefę czasową z django.utils zaimportuj strefę czasową i umieść USE_TZ = True w pliku ustawień projektu.
źródło
Wymyśliłem bardzo proste rozwiązanie:
Działa zarówno z wartościami daty i godziny uwzględniającymi strefę czasową, jak i naiwnymi dla strefy czasowej. I nie są wymagane żadne dodatkowe biblioteki ani obejścia bazy danych.
źródło
Znalazłem, że
timezone.make_aware(datetime.datetime.now())
jest pomocny w django (korzystam z wersji 1.9.1). Niestety, nie można po prostu ustawićdatetime
obiektu na rozpoznawanie przesunięcia, to jesttimetz()
to. Musisz dokonaćdatetime
i dokonać porównań na tej podstawie.źródło
Czy istnieje jakiś naglący powód, dla którego nie można obsłużyć obliczeń wieku w samym PostgreSQL? Coś jak
źródło
Wiem, że to stare, ale pomyślałem, że dodam moje rozwiązanie na wypadek, gdyby ktoś uznał je za przydatne.
Chciałem porównać lokalną naiwną datę i godzinę ze świadomą datą z serwera czasu. Zasadniczo utworzyłem nowy naiwny obiekt datetime przy użyciu świadomego obiektu datetime. To trochę hack i nie wygląda bardzo ładnie, ale wykonuje pracę.
... nadchodzi krówka ...
źródło
utc_to_local()
z mojej odpowiedzi zwraca czas lokalny jako świadomy obiekt datetime (jest to kod Python 3.3+)delta = response.tx_time - time.time()
.