settings.py
TIME_ZONE = 'Asia/Kolkata'
models.py
order_booking_time = models.DateTimeField()
while creating:
"order_booking_time":"2021-10-09 06:00"
What it stores in database:
"2021-10-08T18:53:17.097257+05:30"
So i did this in serializer.py while viewing in data
def get_order_booking_time(self,obj):
date = obj.order_booking_time.strftime("%Y-%m-%d %H:%M:%S")
return str(date)
Output:
"2021-10-09 00:30:00"
which is not equal to what i stored in data i.e."2021-10-09 06:00"
What in the way we retrieve OR store data in this "%Y-%m-%d %H:%M:%S" format with my local time
Having the same issue here. Django stores the datetime in UTC format.
You are accessing the data as stored in the database>
As far as I know Django uses serializers to transform datetime fields. In this case you use the (db) model directly.
Related
We are working on a multi tenant django app that needs to display datetimes in tenant's timezone.
We achieve multitenancy using django-tenants, it separates tenants via Posgresql different schemas.
We are using graphql through graphene to expose our APIs, and we would like to make this implementation transparent to it, thus avoiding to manipulate every datetime we receive in input with timezone.localtime(received_datetime).
We've written a middleware that should do the job but graphene queries keep displaying the naive datetimes, to our understanding this is because django, while timezone aware, manage datetimes timezone only at forms and template levels, as per docs: https://docs.djangoproject.com/en/4.1/topics/i18n/timezones/
When support for time zones is enabled, Django stores datetime information in UTC in the database, uses time-zone-aware datetime objects internally, and translates them to the end user’s time zone in templates and forms.
By looking at timezone.now and timezone.localtime(timezone.now) values we get the correct results, but every date we get from graphql is both aware and with django "from settings" timezone (UTC), instead of tenant's timezone:
timezone.now(). # prints 2022-09-02 13:38:46.658864+00:00
timezone.localtime(timezone.now()) # prints 2022-09-02 22:56:16.620355+09:00
Querying graphql api instead outputs:
"edges”: [
{
“node”: {
“id”: “UG9saWN5Tm9kZToxNQ==“,
“createdAt”: “2022-09-01T13:55:04.542763+00:00" # in UTC timezone, instead of tenant's timezone
}
}
]
middleware.py
class TimezoneMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
tenant = request.tenant
if not tenant.schema_name == "public":
if tenant.timezone:
timezone.activate(pytz.timezone(tenant.timezone))
else:
timezone.deactivate()
return self.get_response(request)
settings.py
...
TIME_ZONE = "UTC"
USE_TZ = True
...
tenant_model.py
class Client(TenantMixin):
TIERS = [
('1', '1'),
('2', '2'),
('3','3')
]
name = models.CharField(max_length=100)
paid_until = models.DateField()
on_trial = models.BooleanField()
tier = models.CharField(max_length=20, choices=TIERS, default = '1')
created_on = models.DateField(auto_now_add=True)
storage_name = models.CharField(max_length=254, default='local')
dashboard_base_url = models.CharField(max_length=254, default='https://foo.bar')
auto_create_schema = True
timezone = models.CharField(max_length=254, default="Asia/Tokyo")
Every datetime we receive in input is a naive datetime (YYYY-MM-DDTHH:mm:ss format), is there any way to automagically (through a middleware) make it aware using tenant's timezone?
I would like to set my DateField's default value to today's date in UTC timezone.
If I put datetime.now(timezone.utc).date(), it will be a fixed value that is called when the server restarts.
If I put timezone.now, it will return datetime object, not day object.
How can I get the today's date in UTC timezone? A function that is callable (without parentheses at the end)
Because if I put timezone.now().date, won't it be called when the server is restarted only, not every time the object is created/updated?
You seem to have mostly solved your own problem. Simple create "a function that is callable".
from datetime import datetime
def today_utc():
return datetime.utcnow().date()
class MyModel(models.Model):
my_field = models.DateField(default=today_utc)
In your settings.py file you must set this var:
USE_TZ = True
Now in your code if you want to get the correct utc now date you do so:
from django.utils import timezone
today = timezone.now().date()
If you have field in your model is DateField, example: my_field do so:
my_field = models.DateFiel(default=date.today)
If you have field called my_field set DateTimeField do so:
my_field = models.DateTimeField(default=timezone.now)
And read the doc
When I save dates in my database Django shows message about succesfull adding with the right time but in fact in the databese time is different
models.py:
from datetime import datetime
from django.db import models
class Teg1(models.Model):
created_at = models.DateTimeField(default=datetime.now, null=True, blank=True, editable=False)
num = models.FloatField(default=0.0, null=True, blank=True)
def __str__(self):
return str(self.num) + " || " + str(self.created_at)
settings.py
TIME_ZONE = 'Asia/Novosibirsk'
USE_TZ = True
The first sentence of Django's time zone documentation explains what you're seeing:
When support for time zones is enabled, Django stores datetime information in UTC in the database, uses time-zone-aware datetime objects internally, and translates them to the end user’s time zone in templates and forms.
So the database value is in UTC. The str() value is also in UTC, since you've manually converted the UTC datetime to a string without changing the timezone. The value interpreted by the form and displayed by the template is in your local time, since templates convert DateTimeFields to the current timezone.
If you want the str() value to use the local timezone you can use Django's localtime() function:
from django.utils.timezone import localtime
class Teg1(models.Model):
...
def __str__(self):
return str(self.num) + " || " + str(localtime(self.created_at))
If i'm not mistaken, you must be in Russia which is 7 hours ahead of UTC. So, the server that you use must be using the UTC time which in my opinion is a good thing.
I personally prefer to save times in UTC time in the data base and then convert them to the local time in the front end.
from django.utils import timezone
from datetime import datetime
teg1 = Teg1(created_at=datetime.now(tz=timezone.utc)
teg1.save()
However, if you want to save the datetime in your local time, you can use:
from datetime import datetime
import pytz
novosibirsk = pytz.timezone("Asia/Novosibirsk")
now = datetime.now(novosibirsk)
teg1 = Teg1(created_at=now)
teg1.save()
Have in mind that in your admin interface, you might see the time and date based on the timezone you select in your settings.py. However, the data saved in the database is still in UTC time.
instead of using
from datetime import datetime
class Teg1(models.Model):
created_at = models.DateTimeField(default=datetime.now)
use (this will use timezone that you have set in settings.py)
from django.utils import timezone
class Teg1(models.Model):
created_at = models.DateTimeField(default=timezone.localtime())
I am doing flask app with flask-sqlalchemy.
I need to save object to db with timestamp provided by client.
For example:
2017-03-03T11:30:00+04:00
I need to save this timestamp with +4 time zone. Model declaration looks like this:
class Appointment(db.Model):
__tablename__ = 'appointments'
id = Column(db.Integer, primary_key=True)
start_time = Column(db.DateTime(timezone=True), nullable=False)
So here I have start_time attribute. I try to save my appointment object like this:
new_appointment = Appointment()
# at this line I convert string time to python datetime
appointment_time = datetime.strptime(string_datetime[:len(string_datetime) - 3] + string_datetime[len(string_datetime) - 2:],
'%Y-%m-%dT%H:%M:%S%z')
new_appointment.start_time = appointment_time
db.session.add(new_appointment)
db.session.commit()
When I check my db, my object is saved with my servers timezone (in this case as +6). I also tried to save without timezone (setting timezone=False), but again timestamp is saved as +6, but without indication of timezone. How do I force my object being saved with provided timzone?
Use pyTZ module
Take UTC time and convert it to desired timezone
from datetime import datetime
from pytz import *
eastern = timezone('US/Eastern')
loc_dt = eastern.localize(datetime(2017, 10, 3, 7, 27, 0))
print loc_dt
Also, you can go through this interesting article detailing problems with the datetime timezone handling
I have configured my timezone in settings, as America/Guatemala and I have some datetime fields in my models, I'm using default=timezone.now but it is not saving my local hour, which is UTC-6:00, is saving it as UTC-00:00. I can't change that because now there is some important data stored in the database in that way.
I have problems retrieving the data in a queryset, I send a string in request.POST like this:
date='1/09/2016'
And I have tried this to configure my date for the query:
f=date.split('/')
if len(f)>1:
initialdate=datetime.datetime(int(f[2]),int(f[1]),int(f[0]),0,0,0,tzinfo=pytz.UTC)
finaldate=datetime.datetime(int(f[2]),int(f[1]),int(f[0]),23,59,59,tzinfo=pytz.UTC)
And this is my queryset:
sale=Sale.objects.filter(Q(pk=int(cod))|Q(sale_date__range=(initialdate,finaldate)))
But because of the 6 hours of difference between my saved data and my local date and time, if I store a Sale at 6:01pm of my local time, the saved data is stored as 00:01am of tomorrow. If i want to check all the sales that I made today, it doesn't show me the sales after 6pm, because they are saved in a different date.
I have another queries where I send two differents dates, and I use the same code, I just add time 0,0,0 to the first date, and 23,59,59 to the second date, but I have the same problem.
My question is, how can I add those six hours to the dates that I use as parameters? I need the datetime to be aware, and I can't change nothing in my model, I can change only the parameters that I'm sending to the queryset.
I am also have the question. and what I am did is that:
the whole day's date range is: 00:00:00 - 23:59:59, and this is the local datetime, but the datetime in datebase has beed transformed to utc, so I just sub the local datetime 6 hour, and you can do so;
import datetime
f=date.split('/')
if len(f)>1:
initialdate=datetime.datetime(int(f[2]),int(f[1]),int(f[0]),0,0,0,tzinfo=pytz.UTC)
finaldate=datetime.datetime(int(f[2]),int(f[1]),int(f[0]),23,59,59,tzinfo=pytz.UTC)
initialdate = initialdate - datetime.timedelta(hours=6)
finaldate = finaldate - datetime.timedelta(hours=6)
import pytz
from django.utils import timezone
initialdate = datetime.datetime.combine(date, datetime.time.min.replace(tzinfo=timezone.UTC())).astimezone(pytz.timezone('America/Guatemala'))
finaldate = datetime.datetime.combine(date, datetime.time.max.replace(tzinfo=timezone.UTC())))).astimezone(pytz.timezone('America/Guatemala'))
Edited to make date aware
To simply change the date six hours back you can use datetime's timedelta.
To change sale_date of objects within your query you simply need to do this:
import datetime
import pytz
for s in sale:
sale_date = sale_date - datetime.timedelta(hours=6)
sale_date = sale_date.replace(tzinfo=pytz.timezone("America/Guatemala"))
s.save()
To change sale_date of all Sale objects:
import datetime
import pytz
all_sales = Sale.objects.all()
for sale in all_sales:
sale_date = sale_date - datetime.timedelta(hours=6)
sale_date = sale_date.replace(tzinfo=pytz.timezone("America/Guatemala"))
sale.save()
Also, to parse strings containing time information use strptime:
import datetime
date='1/09/2016'
parsed_date = datetime.datetime.strptime(date, '%w/%m%Y')
More info on it here