¿Cómo obtengo la zona horaria actual del visitante y luego convierto timezone.now () a la cadena de la hora local en Django 1.4?

Entiendo que la mejor práctica ahora con Django 1.4 es almacenar todos los datos en UTC y estoy de acuerdo con eso. También entiendo que todas las conversaciones de zona horaria se deben realizar en el nivel de la plantilla de esta manera:

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

Sin embargo, necesito convertir la hora UTC a la hora local de la request en Python. No puedo usar las tags de plantilla ya que estoy devolviendo la cadena en JSON usando Ajax (más específicamente Dajaxice ).

Actualmente este es mi código 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' }) 

Entonces, incluso si la hora actual es April 14, 2012, 5:52 pm en la hora EST (mi zona horaria local), la respuesta de JSON regresará April 14, 2012, 9:52 pm , porque esa es la hora UTC.

También noté que Django almacena una variable de plantilla llamada TIME_ZONE para cada solicitud (que en realidad no es parte de la variable de request ), por lo que, dado que my es America/New_York , America/New_York que Django puede descubrir la zona horaria local de cada visitante (basada en HTTP encabezamiento)?

De todos modos, entonces mi pregunta es doble:

  1. ¿Cómo obtengo la zona horaria local del visitante en mi ajax.py ? (Probablemente lo pase como un argumento de cadena como {{ TIME_ZONE }} )
  2. Con la zona horaria local del visitante, ¿cómo convertir la timezone.now() a la zona horaria local y la salida como una cadena utilizando el dateformat de Django?

EDITAR: para @agf

timezone.now() indica la hora UTC cuando 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() 

¿Hay alguna forma de convertir una datetime y datetime a otra que no sea UTC? Por ejemplo, ¿puedo hacer algo como current_time = timezone.now() , luego current_time.replace(tzinfo=est) (EST = Hora estándar del este)?

Necesitas leer los documentos de Django Timezones cuidadosamente.

Un punto importante:

no hay un equivalente del encabezado HTTP Accept-Language que Django podría usar para determinar la zona horaria del usuario automáticamente.

Debe preguntar al usuario cuál es su zona horaria o simplemente usar un valor predeterminado.

También necesita asegurarse de que:

 USE_TZ = True 

en su settings.py .

Una vez que tengas una zona horaria tz , puedes:

 from django.utils import timezone timezone.activate(tz) datetime = timezone.now() if checked else None 

para obtener un objeto de datetime y datetime compatible con la zona horaria en la zona horaria tz .

Si bien el navegador no envía ningún encabezado al servidor que indique una zona horaria, el entorno de JavaScript conoce su zona horaria actual.

Esto tiene dos efectos importantes: aunque el servidor no puede averiguar su zona horaria actual en la solicitud inicial, puede enviar algún código javascript que determinará el desplazamiento TZ y enviará esa información al servidor para que la información de la zona pueda ser asociado a la sesión actual desde ese punto en adelante.

Pero lo que es más importante, si está enviando su valor de tiempo dentro de los datos JSON que serán interpretados por el lado del cliente del navegador, la zona horaria del navegador no necesita ser conocida. En su lugar, solo tiene que asegurarse de que el desplazamiento de la zona horaria esté presente en su salida JSON para que el navegador pueda hacer su propia matemática de la zona horaria después del hecho.

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

Dado que desea las zonas horarias de los usuarios, tiene sentido para mí que esto se haga en el navegador con Javascript.

Paso algo como esto en la plantilla:

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

Donde obj es una instancia de un modelo de django donde el campo de marca de tiempo es de tipo DateTimeField.

La plantilla:

 
{{ t }}
...

Para mí, esto produce algo así como: 15/2/2017, 05:22:24 PM (PST)

La documentación pertinente:

  • Clase de fecha de Javascript (ver especialmente el constructor que acepta cadenas de datos y el método toLocaleFormat ())

  • strftime (viene con muchos accesos directos de formato de fecha)