I have a datetime object that is set to 2014-02-24 19:00:00+00:00 and I believe this is set as UTC by default (through the Django admin panel).
This time is actually Africa/Johannesburg, so I convert it like this:
local_timezone= pytz.timezone("Africa/Johannesburg")
local_time_start = self.start_time_unix.replace(tzinfo=local_timezone)
This will now output 2014-02-24 19:00:00+01:30
Now I want to store this as the converted UTC timezone, so I do it like this:
utc_time = local_time_start.astimezone(utc)
For some reason, this outputs 2014-02-24 17:30:00+00:00. The time is should output is 17:00:00 so where is the extra 30 mins coming from?
Basically I am trying to take the given input from the django admin panel as the local timezone of the models time_zone field, but store it as UTC.
Is there a better way I can approach this? The Django docs explain how to convert the users local timezone but I need to convert it based on the timezone in the models attributes.
Don't use datetime.replace() with pytz timezones. The pytz timezones contain historical timezone data (to allow for dates in the past to use the right offsets from UTC), but datetime.replace() cannot use the correct information in that case.
Use the timezone.localize() method instead:
local_timezone = pytz.timezone("Africa/Johannesburg")
local_time_start = local_timezone.localize(self.start_time_unix)
See the pytz documentation.
Use this only on non-timezone-aware objects. For timezone aware datetime values, use datetime.astimezone() to translate value from one timezone to another:
local_timezone = pytz.timezone("Africa/Johannesburg")
local_time_start = self.start_time_unix.astimezone(local_timezone)
If you have a datetime value that has the wrong timezone attached (it should represent the given time in a different timezone, not a different time in that timezone), remove the old timezone first using .replace(tzinfo=None), then usetimezone.localize()`:
local_timezone = pytz.timezone("Africa/Johannesburg")
local_time_start = local_timezone.localize(self.start_time_unix.replace(tzinfo=None))
Related
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 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)
I have date that I get in specific timezone time, but system deals with it as UTC and later it converts it back in that timezone, messing time.
For example like this:
I get this time: 2014-05-05 10:50:30. its datetime object. It has no timezone info, but I can get timezone info from user that uses that time. The thing is this time is showed as 'Europe/Vilnius' time, but system deals with it as UTC and when it outputs time to user it adds +3 hours showing wrong time. It does not matter if I change timezone to users timezone on that datetime object, it still outputs with +3 hours.
For example (snippet of code):
from datetime import datetime
import pytz
create_date = datetime.strptime(stage_log.create_date, "%Y-%m-%d %H:%M:%S")
tz = pytz.timezone(self.user_id.tz)
create_date = create_date.replace(tzinfo=pytz.utc)
This does not do anything and I still get wrong time.
Is there a way to move time to be correct UTC time(so then system correctly convert to users timezone) like this:
2014-05-05 10:50:30 -> convert to UTC. If timezone is 'Europe/Vilnius', it should convert that time to 2014-05-05 07:50:30. Then when system automatically does conversions it would correctly display 2014-05-05 10:50:30, because thats the time it should display.
Also if there is a way to just get number of hours that given timezone differs from UTC, then I could just do as simple as that:
create_date.replace(hour=create_date.hour-timezone_difference)
While this question does not specifically reference odoo, hopefully the following may help others:
Odoo - convert datetime to UTC:
(note: in this example self.start_date is a fields.Date)
start_date = fields.Datetime.to_string(pytz.timezone(self.env.context['tz']).localize(fields.Datetime.from_string(self.start_date), is_dst=None).astimezone(pytz.utc))
similar but with +24 hrs
end_date = fields.Datetime.to_string(pytz.timezone(self.env.context['tz']).localize(fields.Datetime.from_string(self.end_date), is_dst=None).astimezone(pytz.utc) + timedelta(hours=24))
This was used because the passed values (self.start_date) were field.Date and therefor did not get affected by timezones, while the target stored fields were fields.Datetime and therefor stored in UTC.
start_date/end_date which are now in UTC can then be used in a self.env[''].search([])
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)
So, we have 'Europe/Moscow' TZ in our settings.
Currently this means daylight saving (this is going to change in the future, but at the moment it's UTC+03/04).
I understand that this TZ is used when saving dates to the DB, and when extracting them.
Now, I have to serialize the datetime object to ISO string, including the UTC offset. What is the correct way of doing this?
The dates don't contain the TZ info (i.e. d.strftime('%z') is empty)
I think I could convert them to UTC and serialize with +00:00, but how do I convert them to UTC if I don't know if the specific date is +03 (Moscow winter) or +04 (Moscow summer)
how do I convert them to UTC if I don't know if the specific date is +03 (Moscow winter) or +04 (Moscow summer)
There is no need for UTC conversion, pytz handles such thing for you.
Here's the code to convert from timezone-naive datetime to ISO with timezone offset:
from datetime import datetime
from pytz import timezone
server_timezone = timezone('Europe/Moscow')
server_timezone.localize(datetime(2011, 1, 1)).isoformat()
>>> '2011-01-01T00:00:00+03:00'
server_timezone.localize(datetime(2011, 7, 1)).isoformat()
>>> '2011-07-01T00:00:00+04:00'
First run new_dt = datetime.replace(tzinfo=tz) to create a new timezone-aware datetime. Then run your datetime.strftime() with %z.
Note that you can't then convert the date string back to a timezone-aware datetime directly -- datetime.strptime() doesn't support %z. So you need to instead create a naive datetime and a tzinfo then do datetime.replace(tzinfo=tz) as before.
Some useful external libraries:
http://pytz.sourceforge.net/
http://code.google.com/p/parsedatetime/
http://labix.org/python-dateutil
Also try searching right here on Stack Overflow for more questions on (Python OR django OR appengine) AND (datetime OR timezone OR date OR time OR tzinfo).
ISO-8601 has no notion of "Timezones", only dates and times, and as a convenience, times may be presented with an "offset".
To make matters even more annoying, datetime has only a half-hearted nod in acknowledgement of timezones; the tzinfo attribute on datetime objects is optional, and no implementation of that interface is provided by the main-line python.
The standard answer to this is to just always do everything in UTC; including having the server in UTC, not in local time. This is actually a pretty good idea; it's not the times that are different, only the way individual users prefer to read those times (which is similar to preferring '42' over '0b101010').
You can satisfy your users' (reasonable!) desire to view times in their local timezone by storing the preferred timezone (perhaps just a sitewide preference if everyone is in Moscow) separately from the actual times, and then you can use a robust timezone library (like pytz) to do the formatting to and from local time.