Django: activate() not showing effect - python

I have the following line in python manager.py shell:
>>> import pytz
>>> from django.utils import timezone
>>> zone = "Asia/Kolkata"
>>> timezone.activate(pytz.timezone(zone))
>>> timezone.now()
datetime.datetime(2014, 12, 17, 1, 52, 0, 411937, tzinfo=<UTC>)
But the output which I get is still using UTC. Should not it be converted into "Asia/Kolkata"?
UPDATE
If i use commands suggested by dazedconfused below:
zone = "Asia/Kolkata"
if zone:
timezone.activate(pytz.timezone(zone))
else:
timezone.deactivate()
utc_date = datetime.utcnow()
aware_date = timezone.make_aware(utc_date, timezone.utc)
l_time = timezone.localtime(aware_date, timezone.get_current_timezone())
And now when i try to save it on my database(Mongodb on Mongolab) it gets saved as UTC
I have a DateTimeField in my database.
Although when i save it as a simple string it gets saved in current timezone that is "Asia/kolkata" Output as string: 2014-12-17 11:01:53.028852+05:30

It actually successfully sets the current time zone to "Asia/Kolkata"
You can verify by:
...
>>> timezone.get_current_timezone_name()
'Asia/Kolkata'
From the django documentation:
now():
Returns a datetime that represents the current point in time. Exactly
what’s returned depends on the value of USE_TZ:
If USE_TZ is False, this will be a naive datetime (i.e. a datetime
without an associated timezone) that represents the current time in
the system’s local timezone.
If USE_TZ is True, this will be an aware
datetime representing the current time in UTC. Note that now() will
always return times in UTC regardless of the value of TIME_ZONE; you
can use localtime() to convert to a time in the current time zone.
So, if your system's local timezone is 'Asia/Kolkata', you can set USE_TZ to False in your settings.py and the timezone.now() will return what you want.
Or, you'll have to use localtime() to convert the timezone to yours (continue from your shell results):
...
>>> import datetime
>>> utc_date = datetime.datetime.utcnow()
>>> aware_date = timezone.make_aware(utc_date, timezone.utc)
>>> timezone.localtime(aware_date, timezone.get_current_timezone())
datetime.datetime(2014, 12, 17, 8, 0, 36, 598113, tzinfo=<DstTzInfo 'Asia/Kolkata' IST+5:30:00 STD>)
Lastly, here's the documentation of the make_aware() function

Related

Simply save time as UTC with Django

I get a timestamp (via an extern API). When I try to save that, it always is two hours earlier.
I read some docs like Django Time zones, pytz and dateutil but I still don't understand how to tell Django that this specific time should not be converted to UTC because it already is UTC.
It looks like this:
t = '2020-05-29 08:47:39' # this is UTC
MyModel(
timestamp=t,
…
).save()
In the database it is stored as 2020-05-29 06:47:39. So it is shown on a template e. g. as 2020-05-29 08:47:39 whereas 2020-05-29 10:47:39 would be correct.
settings.py
TIME_ZONE = 'Europe/Berlin'
USE_TZ = True
I think I found the solution by myself: the string t must be converted to a datetime-object including the UTC timezone like this:
>>> t = '2020-05-29 08:47:39'
>>> import datetime
>>> dt = datetime.datetime.strptime(t, '%Y-%m-%d %H:%M:%S')
>>> dt
datetime.datetime(2020, 5, 29, 8, 47, 39)
>>> import pytz
>>> tz = pytz.utc.localize(dt)
>>> tz
datetime.datetime(2020, 5, 29, 8, 47, 39, tzinfo=<UTC>)
Saving this with Django, everything is perfect.

Timezone not working properly in Django

I want to change timezone in Django, so I read documentation how to do it nad here's what I've got:
#settings.py
TIME_ZONE = 'Europe/Ljubljana'
#models.py #date_time gets filled with "auto_now=True")
date_time = models.DateTimeField(auto_now=True)
UTC DST offset for given location (Europe/Ljubljana) is +2, while in my db I see timestamp of UTC. So what am I missing?
Or is this working as intended so it gets processed for each request separately (useful for people in different timezones)? But if this is the case, what's the use of setting TIME_ZONE = 'Europe/Ljubljana'?
From the documentation
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 datetime in your DB will always be stored in UTC, but will be displayed using the correct TZ in templates and forms.
To get the date in correct TZ elsewhere, use astimezone():
>>> from myapp.models import Details
>>> import pytz
>>> d = Details.objects.get(pk=1)
>>> d.added
datetime.datetime(2016, 5, 28, 18, 59, 55, 841193, tzinfo=<UTC>)
>>> localdate = d.added.astimezone(pytz.timezone('Europe/Ljubljana'))
>>> localdate
datetime.datetime(2016, 5, 28, 20, 59, 55, 841193, tzinfo=<DstTzInfo 'Europe/Ljubljana' CEST+2:00:00 DST>)

Specify which timezone a datetime is in, in python

I have a datetime that i get from a database, this datetime is a UTC datetime. But when i pull it from the DB, it is unaware of the timezone. What i need to do, is convert this datetime to a "seconds from epoch" time for another function. The problem with this, is that the system's time is in PST and i am not able to change it for specific reasons.
So, what i want to do is, take this datetime that i get from the database, and tell python that this datetime is a UTC datetime. Every way that i have done that, results in it losing time or gaining time due to timezone conversions. Again, not trying to convert the time, just trying to specify that it is UTC.
If anyone can help with this that would be great.
Thanks!
Example
Assume database_function() returns a datetime data type that is '2013-06-01 01:06:18'
datetime = database_function()
epoch = datetime.strftime('%s')
pytz.utc.localize(database_function()).datetime.strftime('%s')
datetime.replace(tzinfo=pytz.utc).datetime.strftime('%s')
Both of these return a epoch timestamp of 1370077578
But, it SHOULD return a timestamp of 1370048778 per http://www.epochconverter.com/
Remember, this timestamp is a utc timestamp
Using the fabolous pytz:
import datetime, pytz
dt = datetime.datetime(...)
utc_dt = pytz.utc.localize(dt)
This creates a tz-aware datetime object, in UTC.
How about Setting timezone in Python This appears to reset the timezone within your python script. You are changing the time zone that your system sees given the specified time, not changing the specified time into the specified time zone. You probably want to set it to 'UTC'
time.tzset()
Resets the time conversion rules used by the library routines.
The environment variable TZ specifies how this is done.
New in version 2.3.
Availability: Unix.
I do not have this available on my home platform so I could not test it. I had to get this from the previous answer.
The answer marked best on the question is:
>>> import os, time
>>> time.strftime('%X %x %Z')
'12:45:20 08/19/09 CDT'
>>> os.environ['TZ'] = 'Europe/London'
>>> time.tzset()
>>> time.strftime('%X %x %Z')
'18:45:39 08/19/09 BST'
To get the specific values you've listed:
>>> year = time.strftime('%Y')
>>> month = time.strftime('%m')
>>> day = time.strftime('%d')
>>> hour = time.strftime('%H')
>>> minute = time.strftime('%M')
See here for a complete list of directives. Keep in mind that the strftime() function will always return a string, not an integer or other type.
You can Use pytz, which is a time zone definitions package.
from datetime import datetime
from pytz import timezone
fmt = "%Y-%m-%d %H:%M:%S %Z%z"
# 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)
output:
2014-04-04 21:50:55 UTC+0000
2014-04-04 14:50:55 PDT-0700
2014-04-04 23:50:55 CEST+0200
or may be it helps
>> import pytz
>>> import datetime
>>>
>>> now_utc = datetime.datetime.utcnow() #Our UTC naive time from DB,
for the time being here I'm taking it as current system UTC time..
>>> now_utc
datetime.datetime(2011, 5, 9, 6, 36, 39, 883479) # UTC time in Naive
form.
>>>
>>> local_tz = pytz.timezone('Europe/Paris') #Our Local timezone, to
which we want to convert the UTC time.
>>>
>>> now_utc = pytz.utc.localize(now_utc) #Add Timezone information to
UTC time.
>>>
>>> now_utc
datetime.datetime(2011, 5, 9, 6, 36, 39, 883479, tzinfo=<UTC>) # The
full datetime tuple
>>>
>>> local_time = now_utc.astimezone(local\_tz) # Convert to local
time.
>>>
>>> local_time #Current local time in Paris
datetime.datetime(2011, 5, 9, 8, 36, 39, 883479, tzinfo=<DstTzInfo
'Europe/Paris' CEST+2:00:00 DST>)
Here is one way, using the pytz module:
import pytz
utc_datetime = (datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)
+ datetime.timedelta(seconds=seconds_since_epoch)
If you don't want to install the pytz module, you can copy the example UTC class from the datetime documentation (search for "class UTC"):
https://docs.python.org/2/library/datetime.html#tzinfo-objects
Here's stdlib only solution without 3-party modules.
.., this datetime is a UTC datetime. But when i pull it from the DB, it is unaware of the timezone. What i need to do, is convert this datetime to a "seconds from epoch" time for another function.emphasize is mine
To convert an unaware (naive) datetime object that represents time in UTC to POSIX timestamp:
from datetime import datetime
timestamp = (dt_from_db - datetime(1970, 1, 1)).total_seconds()
Example:
>>> from datetime import datetime
>>> dt = datetime.strptime('2013-06-01 01:06:18', '%Y-%m-%d %H:%M:%S')
>>> (dt - datetime(1970, 1, 1)).total_seconds()
1370048778.0
See Converting datetime.date to UTC timestamp in Python that provides solutions for various Python versions.
To answer the question from the title: In general you need pytz library to handle timezones in Python. In particular, you should use .localize method to convert an unaware datetime object into timezone-aware one.
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone() # local timezone whatever it is (just an example)
aware_dt = tz.localize(naive_dt_in_local_timezone, is_dst=None)
is_dst=None asserts that naive_dt_in_local_timezone exists and unambiguous.
Though you don't need it for UTC timezone because it always has the same UTC offset (zero) around the year and in all past years:
import pytz
aware_dt = utc_dt.replace(tzinfo=pytz.utc)
See Python - simplest and most coherent way to get timezone-aware current time in UTC? (it provides a stdlib-only solution):
aware_dt = utc_dt.replace(tzinfo=timezone.utc)

Python Django: tzinfo doesn't work for DB insertion. But why does .now(local_tz) work?

I am using Django.
in settings:
TIME_ZONE = 'Europe/Copenhagen'
USE_TZ = True
Due to DST, clock skips an hour on 2013-3-31. 01:59 goes to 03:00
I views:
The date and time are given in local time. I want these to be inserted as utc.
Code below correctly saves as UTC, but gives RuntimeWarning: DateTimeField received a naive datetime
the_date = datetime.datetime(2013, 3, 31, 1, 59)
hit = hits(date= the_date); hit.save(); # Correctly saved as 00:59:00
the_date = datetime.datetime(2013, 3, 31, 3, 1)
hit = hits(date= the_date); hit.save(); # Correctly saved as 01:01:00
I thought I could avoid the warning by making the datetime aware. It does avoid the warning, but the conversion is now wrong.
tz = timezone(settings.TIME_ZONE)
the_date = datetime.datetime(2013, 3, 31, 3, 1, tzinfo = tz)
hit = hits(date= the_date); hit.save(); # Incorrectly saved as 02:01:00
The following works, with no runtime error:
I have installed pytz.
the_date = local_tz.localize(datetime.datetime(2013, 3, 31, 3, 1))
Getting to my question:
I get that tzinfo doesn't work because it doesn't account for daylight savings time. Fine, I won't use it. But then I was confused when the following seemed to work:
the_date = datetime.datetime.now(local_tz)
This correctly inserted as utc both in wintertime (where it subtracted 1 hour to get utc) and when I changed my computer systime to a date in the summer (where it subtracted 2 hours to get utc).
My question:
Does .now(local_tz) work or did I test it wrong? Why is this different than tzinfo = tz? Or am I using tzinfo wrong?
I recommend converting to UTC as soon as possible and only use UTC internally. Save for cases where you move across timezones (for example a marine vessel) and really need to save timezone information, for the constant timezone case, it's much simpler to just use local time for input/output and convert it to UTC at the user interface.
To convert from localtime to UTC, you need to use the pytz.timezone.normalize method which handles daylight savings time and other timezone transition. See this section of the pytz documentation. In your case, to convert the local datetime to UTC you need the following:
from pytz import timezone, utc
local_tz = timezone(settings.TIME_ZONE)
local_dt = datetime.datetime(2013, 3, 31, 3, 1, tzinfo = local_tz)
utc_dt = utc.normalize(local_dt.astimezone(utc))

how to findout local time using utcoffset and countryname in python

I have countrynames and utcoffset of that country
How to find out out local time in that country using utcoffset?
Check out pytz for looking up timezones by location. Maybe something like this:
>>> import pytz, datetime
>>> pytz.country_timezones['de']
['Europe/Berlin']
>>> matching_tzs = [t for t in pytz.country_timezones['de'] if pytz.timezone(t)._utcoffset.total_seconds() == 3600]
>>> datetime.datetime.now(tz=pytz.timezone(matching_tzs[0]))
datetime.datetime(2011, 5, 6, 17, 5, 26, 174828, tzinfo=<DstTzInfo 'Europe/Berlin' CEST+2:00:00 DST>)
call datetime.now() with the time zone (as a tzinfo object) as an argument.
A country may span several timezones. A utc offset for a place may change through the time.
Given a country code and a utc offset, you could try to find matching timezone from Olson tz database for the current time. Here's variant of #Mu Mind's answer that takes into account current time (otherwise the result can be unexpected for some timezones):
from datetime import datetime, timedelta
import pytz
country_code, utc_offset = 'de', timedelta(hours=1)
# find matching timezones and print corresponding local time
now_in_utc = datetime.now(pytz.utc)
for zonename in pytz.country_timezones[country_code]:
tz = pytz.timezone(zonename)
local_time = now_in_utc.astimezone(tz)
if tz.utcoffset(local_time) == utc_offset: #NOTE: utc offset depends on time
print("%s\t%s" % (tz.zone, local_time.strftime("%Y-%m-%d %H:%M:%S %Z%z")))
Output
Europe/Berlin 2013-12-02 20:42:49 CET+0100
Save the current TZ environ variable value and then do
>>> os.environ['TZ'] = 'US/Eastern'
>>> time.tzset()
And for the library, whatever time function you use will be for the US/Eastern timezone, you c can reset it back to original one later.
Example usage:
>>> time.strftime('%X %x %Z')
'22:54:11 05/06/11 SGT'
>>> os.environ['TZ'] = 'US/Eastern'
>>> time.strftime('%X %x %Z')
'10:54:30 05/06/11 EDT'
Please refer to time module documentation for examples.
working code
utcoffset='+5:30'
utctime=datetime.datetime.utcnow()
hr=utcoffset[0:utcoffset.find(':')]
min=utcoffset[utcoffset.find(':')+1:]
datetimeofclient=datetime.timedelta(hours=int(hr),minutes=int(min))

Categories