I am working on Django based website. I am trying to get correct timezone and time to be displayed. But it is not working properly. I live in Dallas, Texas. So my default timezone is 'America/Chicago'.
My settings.py file has these lines of code.
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
I have datetime, and pytz installed. So when I am trying to save time in database, my codes are,
from datetime import datetime
import pytz
utc = pytz.utc
database = Database.objects.get(id=1)
databas.time = utc.localize(datetime.now())
database.save()
so when I check into database, updated time is 2015-10-20 23:13:04
instead of 2015-10-20 18:13:04
and when I print it out in template by codes below, I get this output Oct. 20, 2015, 1:13 p.m.
{{ database.time|localtime }}
I am confused how to use datetime, pytz and all to get accurate time along with settings.py file.
What I want to do is I want to save UTC time. But when I print out I want to get visitor's timezone and print time according to user. My website will be accessible only in United States for now. My model has
time = models.DateTimeField(auto_now_add=True)
and it is saving some different time. I have another model where I have column named expire time where I am using following codes to save,
expire_time = utc.localize(datetime.now()+ timedelta(hours=24))
means I want to expire a link after 24 hours. But this timezone is confusing me. Can anyone help me? I don't know what should I use in my codes to get proper timezone.
If you set USE_TZ = True Django stores datetimes in UTC. Use the following to create a timezone aware datetime.now:
from django.utils import timezone
from datetime import timedelta
database.time = timezone.now()
expire_time = timezone.now() + timedelta(hours=24)
You can then use activate() to set the current time zone to the end user’s actual time zone.
Have a look at "Selecting the current time zone" to see an example how a user can select his timezone and how this selection is used to activate his timezone.
Related
I'm working on a social media app and I want user A to be able to get all the months with the year that user B posted in user A's time zone. The front-end is in Javascript the most sensible thing would be for a user to send their time zone's offset from UTC (Can be done with new Date().getTimezoneOffset() in JS, so if you're on EET (Eastern European Time) this would return -120 as EET is 120 minutes ahead of UTC) as this is what time zone dates are saved in Django. So for example user A would ping a url that looks something like /<user B's username>/<user A's time zone offset from UTC>.
Let's say user B is in PST and created a post at November 15 2021 12:00pm and December 31 2021 at 11:00pm. Then let's say user A who's in EST calls that url with /<user B username>/<new Date().getTimezoneOffset() in JS> then it should return [(November, 2021), (January, 2022)] (Or the equivalent numerical mapping), because December 31 at 11:00pm PST is January 1st at 2:00am EST.
How can I return all months with year user B posted in user A's time zone, give user A's time zone offset from UTC?
models.py
class Post(models.Model):
uuid = models.UUIDField(primary_key=True)
created = models.DateTimeField('Created at', auto_now_add=True)
updated_at = models.DateTimeField('Last updated at', auto_now=True, blank=True, null=True)
creator = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="post_creator")
body = models.CharField(max_length=POST_MAX_LEN, validators=[MinLengthValidator(POST_MIN_LEN)])
If you enable time zone support in Django (see Django Time zones documentation), you can make queries using time zone-aware datetime objects.
To enable it, you need to set USE_TZ = True in your settings file.
You need to call the timezone.activate method to set the current user's timezone.
Let's assume you're going to send the UTC offset in the URL as above (/<user B username>/<new Date().getTimezoneOffset() in JS>) and that you'll have the offset available in a variable called utc_offset. You can then set the "current time zone" (i.e. the current user's timezone) like this:
import datetime
from django.utils import timezone
timezone.activate(datetime.timezone(datetime.timedelta(hours=utc_offset)))
Now, when you run timezone.now(), the date will be returned in the user's timezone.
And when you render any DateTimeField values in any templates, they will be rendered in the user's timezone.
If you're using Django Rest Framework (DRF), DateTimeFields will also be returned in the user's timezone.
If you're not using DRF or rendering the dates in templates, you could get a datetime value in the user's timezone using astimezone and timezone.get_current_timezone():
post.created.astimezone(timezone.get_current_timezone())
Making queries
If you set USE_TZ = True and filter a model using a timezone-naive datetime, e.g. datetime(2021, 1, 10), Django will do the query in the user's timezone.
First of all, you should get the problems with users B timezone and server timezone!
As you said,
Let's say user B is in PST and created a post at.. and December 31
2021 at 11:00pm.
it depends on your server’s timezone, how it will be recorded in your database! If you servers timezone is UTC, you’ll have a record: 2021-01-01 07:00. What date is it really was, huh? OK, lets guess you have the servers’s timezone in UTC and in DB there will be record that matches 2021-01-01 07:00.
So, all you need in this case is to add offset to datetime and get the month, like this:
def get_month_from_user_side(dt: datetime, offset: int) -> str:
result_dt = dt - timedelta(minutes=offset)
return result_dt.strftime('%B, %Y')
I have tested it:
from datetime import date, datetime, timedelta
if __name__ == '__main__':
user_b_post_dt = datetime(2022, 1, 1, 7, 00) # This time – from DB
offset = -120 # This should be got from JS from user A
print(
get_month_from_user_side(user_b_post_dt, offset)
)
>>January, 2022
The “Magic” here is that if user B will ask for his own posts, he will get December just like it should be!
if __name__ == '__main__':
user_b_post_dt = datetime(2022, 1, 1, 7, 00) # This time – from DB
offset = 480 # PST time offset from UTC (for user B)
print(
get_month_from_user_side(user_b_post_dt, offset)
)
>>December, 2021
Note: This code needs tests to define the sign of +- timedelta, there can be mistake.
Django's guids recommneds to use set USE_TZ=True https://docs.djangoproject.com/en/4.0/topics/i18n/timezones/#setup so I do. I also recommends to set TIME_ZONE = 'UTC'
It sounds like what you need to do is user data storage through datetime(). The best way I have found to accomplish the same problem is to store every user's timezone and reject any duplicated. Then when any user posts data it records every time zones date and time at that moment and saves it with the post. Then when displaying data you detect what timezone the user is in and display that specific timezones date and time from the post that is being displayed.
There is no way to write a query to select objects with a specific timezone. So if you want to do such a query, you either query all posts in that year and then filter the queryset with pure python methods (e.g. filter()); either you add a new field to the post where you save the timezone so you can write your query. This would be a more efficient solution.
Still, I would like to point out that such a query is a bit odd, as any datetime is pointing to an exact moment in time and it looks like you're not interested in a time-range, but only the timezone... Maybe the location is what you're after, or a larger area at least.
I currently have TIME_ZONE = 'UTC' set in my settings.
In my DebitCard model expiration_date field, I store the date as a unixtime. For instance 01/10/2020 #11:25pm (UTC) is 1578698708.
The problem is:
Let's say the expiration_date is January 15th, 2010 at 00:00 or (1263513600).
I want to block users from making a transaction when the current time is greater than the expiration_date.
However, if the user is in LA (8 hours before UTC), the current_time will be off by 8 hours.
Question:
How do I grab the user's current time wherever they are (not just in LA)? Because I want to grab this time and compare it to their debit card expiration_date
Try this.
from django.contrib.gis.utils import GeoIP
from .utils import GeoTimeZoneReader
g = GeoIP() # get user ip
g.city(request.META['REMOTE_ADDR'])
g.city('74.125.79.147') # get city
to get timezone
data = GeoIP().city('74.125.79.147')
# Get Time Zone
db = GeoTimeZoneReader()
db.get_timezone(data['country_code'], data['region'])
If you want to be sure that your code is using UTC time to do the comparison, use datetime.datetime.utcnow()
For example, try running the following in python or in your manage.py shell:
import datetime
print(datetime.datetime.utcnow())
You can compare the output of that to a simple datetime.datetime.now(). If the computer you're using is not in UTC, now() and utcnow() will be different.
As long as I'm using plain ol' Python shell, the datetime.datetime.now() command works fine to get system's local (non-UTC) time.
But I'm working on a Django project where the time zone is changed in settings.py with TIME_ZONE = 'UTC'.
I've tried many solutions from django.utils timezone to tzlocal module, but none of them works. All of them return either incorrect or UTC time.
All of the solutions work if I change the timezone in settings.py to my local timezone. But I can't do that, so is there any way to bypass the default timezone option in settings.py? Or any way the settings.py's timezone can be automatically updated? If I remove the TIME_ZONE line, I don't know why, but it seems to get a random timezone.
EDIT -
I know that the timezone can be entered manually with pytz, but I don't want to do that. I want to get the local system timezone, but WITHOUT Django's moderation of the timezone.
Thanks.
Django seems to be putting its timezone in the TZ environment variable. Try del os.environ['TZ'] then using tzlocal.
To get the time for a different timezone, use this code:
# create another timezone instance
import pytz
new_york_tz = pytz.timezone("America/New_York")
# get the current date and time, with the timezone set in your settings.py
from django.utils import timezone
d = timezone.now()
print(d)
# get the date and time in your other timezone
d2 = new_york_tz.normalize(d)
print(d2)
See: https://docs.djangoproject.com/en/1.10/topics/i18n/timezones/#naive-and-aware-datetime-objects
You can use Javascript to get the Timezone Offset from browser to UTC. Here is the code.
var d = new Date()
var n = d.getTimezoneOffset()
alert(n)
The result is the amount of minutes. For example, you will get 480 in Los Angeles. if the result is negative number, the timezone should be the "West", opposite, the positive number means "East". AND 1 timezone = 60 minutes, so, you can figure out 480 / 60 = 8. Then the result is Los Angeles is in the west 8 timezone. Then you can use pytz to get the local time.
I want to format a datetime to the user's localtime. I do not want to do it in a template though, I want to do it in the .py file and pass it to the template for display as is. What facility do the template code use to do this? Can I get at this from my .py file?
You need to start using Django's Time Zones:
set USE_TZ to True
install pytz module (recommended)
set the default TIME_ZONE
Then, in order to make time-zone-aware datetimes, you need to somehow determine the user's timezone. The most reliable way would be to let the user choose the timezone and remember the choice for every user. Then, in the view activate the specific user's timezone:
import pytz
from django.utils import timezone
tzname = request.session.get('django_timezone') # or wherever you store the user's timezone
if tzname:
timezone.activate(pytz.timezone(tzname))
else:
timezone.deactivate()
print timezone.now()
Also see:
Selecting the current time zone (has the view-to-template example)
When should I activate/deactivate the current timezone in Django (1.4)?
How do I get the visitor's current timezone then convert timezone.now() to string of the local time in Django 1.4?
Hope that helps.
In OpenERP, when I try to print the current date and time, it always print the 'UTC' time. But I want to get time in the user timezone . Each user have different timezone.For example 'CST6CDT', 'US/Pacific' or 'Asia/Calcutta'. So I need to get time in user timezone so that I can show the correct datetime in the report. I have tried to change the timezone using localize() and replace() function in datatime module. But I didn't get the correct output.
Got it.
from datetime import datetime
from pytz import timezone
fmt = "%Y-%m-%d %H:%M:%S"
# Current time in UTC
now_utc = datetime.now(timezone('UTC'))
print now_utc.strftime(fmt)
# Convert to US/Pacific time zone
now_pacific = now_utc.astimezone(timezone('US/Pacific'))
print now_pacific.strftime(fmt)
# Convert to Europe/Berlin time zone
now_berlin = now_pacific.astimezone(timezone('Europe/Berlin'))
print now_berlin.strftime(fmt)
Courtesy: http://www.saltycrane.com/blog/2009/05/converting-time-zones-datetime-objects-python/
As of OpenERP 6.1 the timezone of all Python operations happening on the server-side (and in modules) is forced to be UTC. This was a design decision explained in various places [1]. The rendering of datetime values in the user's timezone is meant to be done on the client-side exclusively.
There are very few cases where it makes sense to use the user's timezone instead of UTC on the server-side, but indeed printing datetime values inside reports is one of them, because the client-side will have no chance to convert the contents of the resulting report.
That's why the report engine provides a utility method for doing so: the formatLang() method that is provided in the context of reports (RML-based ones at least) will format the date according to the timezone of the user if you call it with a datetime value and with date_time=True (it uses the tz context variable passed in RPC calls and based on the user's timezone preferences)
You can find example of how this is used in the official addons, for example in the delivery module (l.171).
Have a look at the implementation of formatLang() if you want to know how it actually does the conversion.
[1]: See the OpenERP 6.1 release notes, this other question, as well as comment #4 on bug 918257 or bug 925361.
from: http://help.openerp.com/question/30906/how-to-get-users-timezone-for-python/
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
import pytz
from openerp import SUPERUSER_ID
# get user's timezone
user_pool = self.pool.get('res.users')
user = user_pool.browse(cr, SUPERUSER_ID, uid)
tz = pytz.timezone(user.context_tz) or pytz.utc
# get localized dates
localized_datetime = pytz.utc.localize(datetime.datetime.strptime(utc_datetime,DATETIME_FORMAT)).astimezone(tz)
DateInUTC = <~ Time variable to convert
To convert to user's timezone:
LocalizedDate = fields.datetime.context_timestamp(cr, uid, DateInUTC, context=context)
To remove the offset:
LocalizedDate = LocalizedDate.replace(tzinfo=None)