I'm encountering a strange issue with timezones in python that I've boiled down to a few lines of code:
from datetime import time, datetime
import pytz
tz = pytz.timezone('Canada/Pacific')
d = datetime.now(tz=tz)
t = time(tzinfo=tz)
When inspecting the tzinfo objects in d and t, the one in t gives a timezone with a utc-offset of 8:12, while the one in d gives a utc-offset of just 8 hours, which is the correct offset. The tz instance also gives a utc-offset of 8:12. What's with the extra 12 minutes?
I realize that datetime.now() is dependent on when you run the code, so I will say that I ran it a few minutes before posting this on StackOverflow and saw the same error. Can someone more knowledgable on timezones help me figure out what the problem is?
pytz is indeed strange. The standard python way since year 2018 is
import datetime
import zoneinfo
ca_pa = zoneinfo.ZoneInfo("Canada/Pacific")
datetime.datetime.now(ca_pa)
Do not use pytz anymore.
#Ruli the answer is just to read the documentation.
tz = pytz.timezone('Canada/Pacific')
dt = tz.normalize(datetime.now())
t = tz.normalize(time())
is the correct way of creating local times.
Related
I want to store in my data base the time stamp of an operation. The problem is that the time that I get from datetime.datetime.now()is incorrect (I guess it's due to time zone). I tried getting the value in the terminal using python and got the correct result.
import datetime
datetime.datetime.now()//correct time
However if I print the result during problem execution the output is incorrect, the result is two hours earlier.
Why is it like that, that the terminal gives me the correct time but the program instance isn't, how can I get the correct time in my program?
Edit:
The date time from the terminal:
2018-08-30 17:41:04.413187
The date time from program instance:
2018-08-30 14:42:31.761310
Edit:
I noticed that I have this warning when I run the program.
RuntimeWarning: DateTimeField Policy.last_update received a naive datetime (2018-08-30 15:16:23.689896) while time zone support is active.
RuntimeWarning)
Try this adjusting the number of hours depending on the timezone you are:
import datetime
datetime.datetime.utcnow()+datetime.timedelta(hours=3)
This works for me:
import pytz
import datetime
timezone = pytz.timezone('Europe/Madrid')
now = datetime.datetime.now(tz = timezone)
install pytz: pip install pytz
get all timezones: print(pytz.all_timezones)
I have a naïve datetime in hand and I want to promote it to include the system timezone. I see lots of examples where the timezone is known a priori and the datetime is localized against it. How do I obtain the local timezone if I don't know it in advance?
local_tz = ???
dt = local_tz.localize(naive_time)
You can get the appropriate local_tz by doing:
import time
import pytz
local_tz = pytz.timezone(time.tzname[0])
EDIT: It appears that time.tzname[0] isn't always a name that corresponds to those found in pytz.all_timezones
The simplest solution is to use the tzlocal package, which uses a number of tricks to find the local timezone from the system, and can also localize for you in place of pytz:
import tzlocal
local_tz = tzlocal.get_localzone()
local_tz.localize(naive_time)
Here is as close as I've managed to get:
local_tz = dateutil.tz.tzlocal()
timestamp = timestamp.replace(tzinfo=local_tz)
Unfortunately local_tz doesn't have a localize() method so I resorted to using replace().
I have an event I would like to trigger in Python, every weekend between Friday morning and Sunday morning.
I have wrote some code that works on my local environment but I'm afraid when deployed to production, the date time will be localised and the trigger will be incorrect.
Ideally I would like everything to be synced to UTC, here's my attempt - I'd like to see if it's correct and if anyone has feedback on how to make it cleaner.
(The code works for me but I'm in the correct timezone anyway :) )
from datetime import datetime
def eventTrigger():
if((datetime.weekday(datetime.today()) == 4) and (datetime.now().utcnow.hour) > 9):
return True
elif ((datetime.weekday(datetime.today()) == 6) and (datetime.now().utcnow.hour) < 10):
return True
elif (datetime.weekday(datetime.today()) == 5):
return True
else:
return False
I tried reading the datetime documentation but it's pretty confusing.
If you want to do this with the Python 3 standard library and without external dependency on pytz:
from datetime import datetime, timezone
now_utc = datetime.utcnow().replace(tzinfo=timezone.utc)
today_utc = now_utc.date()
Datetimes and timezones are confusing, it's good you're making sure to be deliberate here.
First, library pytz can help
from datetime import datetime
import pytz
Then, you can define today and now variables, to be reliably UTC, at the top of your eventTrigger() with:
now_utc = datetime.now(pytz.utc)
today_utc = now_utc.date()
I'm trying to convert a timestamp with a specific timezone(Europe/Paris) to a datetime format in UTC.
From my laptop it works with the solution below but when I'm executing my code in a remote server(AWS- Lambda function in Ireland), I've a shift of 1 hour because the local timezone of the server is different from mine.
How can I have a code who can work on my laptop and at the same time in a remote server(dynamically handle local timezone)?
import pytz
import datetime
def convert_timestamp_in_datetime_utc(timestamp_received):
utc = pytz.timezone('UTC')
now_in_utc = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(pytz.UTC)
fr = pytz.timezone('Europe/Paris')
new_date = datetime.datetime.fromtimestamp(timestamp_received)
return fr.localize(new_date, is_dst=None).astimezone(pytz.UTC)
Thanks
I am not sure what timestamp_received is, but I think what you want is utcfromtimestamp()
import pytz
from datetime import datetime
def convert_timestamp_in_datetime_utc(timestamp_received):
dt_naive_utc = datetime.utcfromtimestamp(timestamp_received)
return dt_naive_utc.replace(tzinfo=pytz.utc)
For completeness, here is another way to accomplish the same thing by referencing python-dateutil's tzlocal time zone:
from dateutil import tz
from datetime import datetime
def convert_timestamp_in_datetime_utc(timestamp_received):
dt_local = datetime.fromtimestamp(timestamp_received, tz.tzlocal())
if tz.datetime_ambiguous(dt_local):
raise AmbiguousTimeError
if tz.datetime_imaginary(dt_local):
raise ImaginaryTimeError
return dt_local.astimezone(tz.tzutc())
class AmbiguousTimeError(ValueError):
pass
class ImaginaryTimeError(ValueError):
pass
(I added in the AmbiguousTimeError and ImaginaryTimeError conditions to mimic the pytz interface.) Note that I'm including this just in case you have a similar problem that needs to make reference to the local time zone for some reason - if you have something that will give you the right answer in UTC, it's best to use that and then use astimezone to get it into whatever local zone you want it in.
How it works
Since you expressed that you were still a bit confused about how this works in the comments, I thought I would clarify why this works. There are two functions that convert timestamps to datetime.datetime objects, datetime.datetime.fromtimestamp(timestamp, tz=None) and datetime.datetime.utcfromtimestamp(timestamp):
utcfromtimestamp(timestamp) will give you a naive datetime that represents the time in UTC. You can then do dt.replace(tzinfo=pytz.utc) (or any other utc implementation - datetime.timezone.utc, dateutil.tz.tzutc(), etc) to get an aware datetime and convert it to whatever time zone you want.
fromtimestamp(timestamp, tz=None), when tz is not None, will give you an aware datetime equivalent to utcfromtimestamp(timestamp).replace(tzinfo=timezone.utc).astimezone(tz). If tz is None, instead of converting too the specified time zone, it converts to your local time (equivalent to dateutil.tz.tzlocal()), and then returns a naive datetime.
Starting in Python 3.6, you can use datetime.datetime.astimezone(tz=None) on naive datetimes, and the time zone will be assumed to be system local time. So if you're developing a Python >= 3.6 application or library, you can use datetime.fromtimestamp(timestamp).astimezone(whatever_timezone) or datetime.utcfromtimestamp(timestamp).replace(tzinfo=timezone.utc).astimezone(whatever_timezone) as equivalents.
I have working code. My question is why does this work?
#"04/13/05 2:30pm EDT" <- original date string
from datetime import datetime, timedelta
from pytz import timezone
import pytz
import time
T= time.struct_time((2005,4,13,14,30,0,0,0,1))
t = time.mktime(T)
print(t)
this prints
1113417000,
which according to an online converter, http://www.epochconverter.com/, prints
Your time zone: 4/13/2005 2:30:00 PM GMT-4
which is correct. My question is, how does it know the time was in EDT which is GMT-4? The last of the 9-tuple is "dst flag", but there are numerous timezones where DST is used. So how does it detect the correct timezone?
It asks your operating system for that information, by way of the stdlib C time functions.
To quote the time module documentation:
Most of the functions defined in this module call platform C library functions with the same name. It may sometimes be helpful to consult the platform documentation, because the semantics of these functions varies among platforms.
You can pass in a -1 for the DST flag to have the library set it for you, see time.struct_time. On my Mac OS X 10.7.5 setup, configured for the Europe/Oslo timezone, that gives me:
>>> import time
>>> time.mktime((2005,4,13,14,30,0,0,0,-1))
1113395400.0
or, as 'translated' by epochconverter:
Your time zone: 4/13/2005 2:30:00 PM GMT+2
According to the documentation the function time.mktime(t) takes an argument (struct_time) expressed in local time, not UTC. Local time is taken from your operating system. You can see your local DST timezone with, for example, time.tzname