I have USE_TZ = True
enabled in my settings.py file, so dateTime values are stored as UTC. When I want to display these dates/times on a template, they will be displayed in whatever timezone I have set in setings.py with TIME_ZONE = 'America/Toronto'
.
But what if my users are in different timezones and I want it to automatically change the time based on the users timezone?
I found that using javascript I can do :
new Date(djangoDate)).toLocaleString()
will format the date and time to my timezone, regardless of what I have in TIME_ZONE = 'America/Toronto'
But is there a way to do this in python/Django?
Everything I have tried, like {% load tz %}
relies on TIME_ZONE = 'America/Toronto'
. in settings.py.
I have also tried:
timezone.activate(pytz.timezone('America/Winnipeg'))
in my view, which seems to display the dates as intended, but found that this will actually change the UTC value in the database when using forms to update dateTime data, which is behavior I do not want.
I want to store in UTC, and render/display in local time, automatically without the user having to tell the application what timezone they are in. Is this possible?
Edit
Elaborating on timezone.activate - it will remove 1 hour from buildStart
when form is submitted, without user changing this field
views.py:
class BuildUpdateView_Building(LoginRequiredMixin,UpdateView):
model = Build
form_class = EditBuild_building
template_name = 'build_edit_building.html'
login_url = 'login'
def get(self, request, *args, **kwargs):
proceed = True
try:
instance = Build.objects.get(id = (self.kwargs['pk']))
except:
return HttpResponse("<h2 style = 'margin:2em;'>This build is no longer available it has been deleted, please please return to dashboard</h2>")
if instance.buildActive == False:
proceed = False
if instance.deleted == True:
proceed = False
#all appears to be well, process request
if proceed == True:
form = self.form_class(instance=instance)
timezone.activate(pytz.timezone(self.request.user.t_zone))
customer = self.request.user.PSScustomer
choices = [(item.id, (str(item.first_name) + ' ' + str(item.last_name))) for item in CustomUser.objects.filter(isDevice=False, PSScustomer = customer)]
choices.insert(0, ('', 'Unconfirmed'))
form.fields['buildStrategyBy'].choices = choices
form.fields['buildProgrammedBy'].choices = choices
form.fields['operator'].choices = choices
form.fields['powder'].queryset = Powder.objects.filter(PSScustomer = customer)
context = {}
context['buildID'] = self.kwargs['pk']
context['build'] = Build.objects.get(id = (self.kwargs['pk']))
return render(request, self.template_name, {'form': form, 'context': context})
else:
return HttpResponse("<h2 style = 'margin:2em;'>This build is no longer editable here, or has been deleted, please return to dashboard</h2>")
def form_valid(self, form):
proceed = True
try:
instance = Build.objects.get(id = (self.kwargs['pk']))
except:
return HttpResponse("<h2 style = 'margin:2em;'>This build is no longer available it has been deleted, please please return to dashboard</h2>")
if instance.buildActive == False:
proceed = False
if instance.deleted == True:
proceed = False
#all appears to be well, process request
if proceed == True:
form.instance.editedBy = (self.request.user.first_name)+ " " +(self.request.user.last_name)
form.instance.editedDate = timezone.now()
print('edited date ' + str(form.instance.editedDate))
form.instance.reviewed = True
next = self.request.POST['next'] #grabs prev url from form template
form.save()
build = Build.objects.get(id = self.kwargs['pk'])
if build.buildLength >0:
anticipated_end = build.buildStart + (timedelta(hours = float(build.buildLength)))
print(anticipated_end)
else:
anticipated_end = None
build.anticipatedEnd = anticipated_end
build.save()
build_thres_updater(self.kwargs['pk'])#this is function above, it updates threshold alarm counts on the build
return HttpResponseRedirect(next) #returns to this page after valid form submission
else:
return HttpResponse("<h2 style = 'margin:2em;'>This build is no longer available it has been deleted, please please return to dashboard</h2>")
form.py
class EditBuild_building(forms.ModelForm):
buildStart = forms.DateTimeField(input_formats = ['%Y-%m-%dT%H:%M'],widget = forms.DateTimeInput(attrs={'type': 'datetime-local','class': 'form-control'},format='%Y-%m-%dT%H:%M'), label = "Build Start Time")
def __init__(self, *args, **kwargs):# for ensuring fields are not left empty
super(EditBuild_building, self).__init__(*args, **kwargs)
self.fields['buildDescrip'].required = True
class Meta:
model = Build
fields = ['buildDescrip', 'buildStart','buildLength','project', 'customer','powder','buildNotes','buildLayerHeight',
'parameters','recoaterType','buildProgrammedBy','buildStrategyBy','operator',
'tempHighThres','tempLowThres',
'humidHighThres','humidLowThres','hardRecoatThres',]
labels = {
'buildDescrip': ('Build Description'),
'buildStart': ('Build Start Time'),
'buildLength': ('Build Length (hours)'),
'buildNotes': ('Build Notes'),
'powder': ('Powder Used for Build'),
'tempHighThres': ('High Temperature Alarm (℃)'),
'tempLowThres': ('Low Temperature Alarm (℃)'),
'humidHighThres': ('High Humidity Alarm (%)'),
'humidLowThres': ('Low Humidity Alarm (%)'),
'hardRecoatThres': ('Hard Recoat Threshold'),
'buildLayerHeight': ('Layer Height (microns)'),
'recoaterType': ('Recoater Type'),
'customer': ('Customer'),
'operator': ('Machine Setup by'),
'project': ('Project'),
'parameters': ('Build Parameters'),
'buildProgrammedBy': ('Build Programmed by'),
'buildStrategyBy': ('Build Strategy by'),
}
widgets = {'buildDescrip': forms.TextInput(attrs={'class': 'required'}),
When I submit this form, it will subtract one hour from buildStart
in the database. It also sets the seconds to 00 for some reason?
When I remove timezone.activate
this behavior disappears...
It appears to subtract the hour on the form.save()
operation