2012-04-14 16 views
6

Rozumiem, że najlepszą praktyką teraz z Django 1.4 jest przechowywanie wszystkich datetime w UTC i zgadzam się z tym. Rozumiem też, że wszystkie rozmowy stref czasowych powinny być wykonywane na poziomie szablonu tak:Jak uzyskać aktualną strefę czasową odwiedzającego, a następnie przekonwertować timezone.now() na ciąg czasu lokalnego w Django 1.4?

{% load tz %} 

{% timezone "Europe/Paris" %} 
    Paris time: {{ value }} 
{% endtimezone %} 

Jednak muszę konwertować czasu UTC na czas lokalny request wszystko jest w Pythonie. Nie mogę używać znaczników szablonów, ponieważ zwracam ciąg znaków w JSON, używając Ajax (dokładniej: Dajaxice).

Obecnie jest to mój kod ajax.py:

# checked is from the checkbox's this.value (Javascript). 
datetime = timezone.now() if checked else None 

$ order_pk is sent to the Ajax function. 
order = Order.objects.get(pk=order_pk) 
order.time = datetime 
order.save() 

return simplejson.dumps({ 
    'error': False, 
    'datetime': dateformat.format(datetime, 'F j, Y, P') if checked else 'None' 
}) 

Więc nawet jeśli obecny czas jest April 14, 2012, 5:52 p.m. czasu EST (mój lokalnej strefy czasowej), odpowiedź JSON powróci April 14, 2012, 9:52 p.m, bo to jest czas UTC.

Również zauważyłem, że Django przechowuje zmiennej szablonu o nazwie TIME_ZONE na każde żądanie (w rzeczywistości nie jest częścią zmiennej request), więc skoro mój jest America/New_York, jestem przy założeniu, że Django może dowiedzieć się każdy odwiedzający własną lokalną strefę czasową (w oparciu w nagłówku HTTP)?

W każdym razie, więc moje pytanie jest dwojaki:

  1. Jak uzyskać lokalną strefę czasową odwiedzającego w moim ajax.py? (Prawdopodobnie przekazać go jako argument łańcuchowy, taki jak {{ TIME_ZONE }})
  2. W lokalnej strefie czasowej gościa, jak przekonwertować UTC timezone.now() na lokalną strefę czasową i wypisać jako ciąg znaków przy użyciu Django: dateformat?

EDIT: dla @agf

timezone.now() daje czas UTC, kiedy USE_TZ = True:

# From django.utils.timezone 
def now(): 
    """ 
    Returns an aware or naive datetime.datetime, depending on settings.USE_TZ. 
    """ 
    if settings.USE_TZ: 
     # timeit shows that datetime.now(tz=utc) is 24% slower 
     return datetime.utcnow().replace(tzinfo=utc) 
    else: 
     return datetime.now() 

Czy mimo przekonwertować datetime do czegoś innego niż UTC? Na przykład, czy mogę zrobić coś takiego, jak current_time = timezone.now(), a następnie current_time.replace(tzinfo=est) (EST = Eastern Standard Time)?

Odpowiedz

10

Należy uważnie przeczytać Django Timezones docs.

Jedna ważna uwaga:

nie ma odpowiednika w nagłówku HTTP Accept-Language że Django mógłby wykorzystać do określenia strefy czasowej użytkownika automatycznie.

Musisz zapytać użytkownika o jego strefę czasową lub po prostu użyć wartości domyślnej.

Należy również upewnić się, że:

USE_TZ = True 

w swoją settings.py.

Gdy masz czasową tz można:

from django.utils import timezone 

timezone.activate(tz) 

datetime = timezone.now() if checked else None 

uzyskać strefy czasowej świadomy datetime obiekt w strefie czasowej tz.

+0

Cóż ja najpierw trzeba zrobić 'timezone.now()' 'przed timezone.activate (TZ)' i przechowywać że do 'order' pierwszego prawa? Ale wtedy będzie 2 różne 'datetime'. – hobbes3

+0

@ hobbes3, jeśli chcesz mieć domyślną strefę czasową dla domyślnej strefy czasowej, a następnie tak. Jeśli chcesz mieć godzinę czasu UTC uświadamiającą strefę czasową, a domyślną strefą czasową nie jest UTC, to musisz przekonwertować ją na UTC. – agf

+0

@ hobbes3 Zawsze możesz użyć 'somedatetime.replace (tz = sometz)'. – agf

6

Podczas gdy przeglądarka nie wysyła żadnych nagłówków do serwera, który wskazywałby strefę czasową, środowisko JavaScript zna zna swoją aktualną strefę czasową.

Ma to dwa ważne skutki: Gdy serwer nie może znaleźć aktualnej strefy czasowej na początkowym żądaniu, możesz wysłać wysłać kod javascript, który określi przesunięcie TZ i wyśle ​​te informacje z powrotem do serwera, więc że informacje o strefie mogą być powiązane z bieżącą sesją od tego momentu do przodu.

Ale co ważniejsze, jeśli przesyłasz swoją wartość czasu do danych JSON, które będą interpretowane przez klienta przeglądarki, strefa czasowa przeglądarki nie musi być znana jako . Zamiast tego, musisz tylko zapewnić, że przesunięcie strefy czasowej jest obecne w twoim wyjściu JSON, aby przeglądarka mogła wykonać swoją własną matematyczną strefę czasową po fakcie.

var now = new Date() 
var offset_minutes = now.getTimezoneOffset() # e.g. 240 for GMT-0400 
1

Ponieważ chcesz stref czasowych użytkowników, ma to dla mnie sens, że należy to zrobić w przeglądarce JavaScript.

mijam coś takiego do szablonu:

{"t": str(obj.timestamp)) 

Gdzie obj jest instancją modelu django gdzie pole timestamp jest typu DateTimeField.

Szablon:

<div class="timestring">{{ t }}</div> 
... 
<script> 
    $('.timestring').each(function(){ 
    var d = new Date($(this).text()); 
    $(this).text(d.toLocaleDateString() + ", " + d.toLocaleFormat("%r (%Z)")); 
    }) 
</script> 

Dla mnie to wyprowadza coś takiego: 2/15/2017, 05:22:24 PM (PST)

odpowiedniej dokumentacji:

Powiązane problemy