Get current time zone (Django) - python

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.

Related

Django - Return months and years that posts by a user spans given time offset from UTC

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.

How can I make django model datetime field data of midnight and timezone aware?

I am trying to set expire_time in my django model to be midnight of user's selected date with timezone aware. But I am not able to get it properly. Can anyone tell me how I can do it or where I am making mistake in my code?
My codes are,
date = datetime.strptime(str(request.POST.get('expire') + ', 23:59:59'),
'%Y-%m-%d, %H:%M:%S')
tz = timezone.get_current_timezone()
date_tz = tz.localize(date)
createEventInDB.ev_expire = date_tz
try:
createEventInDB.save()
except Exception as e:
error = e
So if I select date which is December 1st 2015, it would be posting as 2015-12-1
I want to save data in database like 2015-12-01 23:59:59. I want to give whole day to user. My current timezone is America/Chicago. I have set active timezone by ip. So I want to make it like user can post from anywhere but timezone must be UTC aware and expire at midnight. Can anyone tell me how can I make it possible?
based on the documentation at https://docs.djangoproject.com/en/1.8/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.
So all this is completely unnecessary and all you need to do is use the models.DateTimeField like you always did.
You can define a Date widget in the view or form and alter Time of DateTimeField later on to 23:59:59 before saving (or you can provide it as a default) and Django will automatically convert it to UTC before saving.
I want to do is 2015-12-01 23:59:59 utc
Your code in the question returns 23:59:59 in the current time zone.
It is even simpler to return "23:59:59 UTC" instead given the corresponding UTC date:
from datetime import datetime
import pytz
ev_expire = datetime(utc_date.year, utc_date.month, utc_date.day, 23, 59, 59,
tzinfo=pytz.utc)

Python-Django timezone is not working properly

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.

How to get user's local timezone other than server timezone(UTC) in python?

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)

Python Django: Time Zone Conversion

I'm parsing an XML file that has the dates in GMT time. It's my first time working with timezones so I'm having some difficulty displaying the right time. In the XML file the date is like this.
2015-06-29 23:05
I set up my model with a basic datetime field like this:
date = models.DateTimeField()
...my settings.py has:
USE_TZ = True
TIME_ZONE = 'America/Toronto'
However when I display the time via views it shows 3:05. Not exactly sure what I'm suppost to do next.
Well, there is no way to determine the time zone of the date time you provided. If you know that it is always GMT, then convert from GMT to your local time zone which is "America/Toronto" in your case.
If possible, I'd recommend changing the date format in your XML. Use UTC, as it provides time zone info.
Check this link out: Python - Convert UTC datetime string to local datetime
Readings I recommend for dealing with time.
UTC: http://www.w3.org/TR/NOTE-datetime
Django Time Zone Docs: https://docs.djangoproject.com/en/1.8/topics/i18n/timezones/

Categories