I'm trying to perform a, to me, simple task of generating a current date/time combo at a speficic time zone. All I see is suggestions to use pytz even though datetime includes the tzinfo class to deal with timezones. However, if I try to use tzinfo, it does not work:
>>> from datetime import datetime, tzinfo
>>> d = datetime.now(tzinfo.tzname("EDT"))
TypeError: descriptor 'tzname' requires a 'datetime.tzinfo' object but received a 'str'
The docs say you can use a time zone name like "EDT" or "GMT". What's wrong with this?
The function tzinfo.tzname does the opposite of what you think it does.
It takes a datetime object and returns a string indicating the time zone.
Related
Found this issues working with timestamp conversions where the .timestamp() seem to compensate for time offset even though I created the datetime object with utcnow() method. So what is the reason for the utcnow() method if it actually fails when converting to timestamp later on?
def test_timestamp_issues():
now = datetime.now()
utc_now = datetime.utcnow()
utc_now_with_tz = datetime.now(timezone.utc)
print(f"Now: {now} -- As Timestamp: {now.timestamp()}")
print(f"Utc Now: {utc_now} -- As TimeStamp: {utc_now.timestamp()} "
f"with builtin: {datetime.timestamp(utc_now)}, with setting timezone hard: "
f"{utc_now.replace(tzinfo=timezone.utc).timestamp()}")
print(f"Utc Now: {utc_now_with_tz} -- As TimeStamp: {utc_now_with_tz.timestamp()} "
f"with builtin: {datetime.timestamp(utc_now_with_tz)}, with setting timezone hard: "
f"{utc_now_with_tz.replace(tzinfo=timezone.utc).timestamp()}")
Output:
Now: 2022-04-25 09:12:16.881608 -- As Timestamp: 1650870736.881608
Utc Now: 2022-04-25 07:12:16.881613 -- As TimeStamp: 1650863536.881613 with builtin: 1650863536.881613, with setting timezone hard: 1650870736.881613
Utc Now: 2022-04-25 07:12:16.881753+00:00 -- As TimeStamp: 1650870736.881753 with builtin: 1650870736.881753, with setting timezone hard: 1650870736.881753
The expected timestamp here should be 1650870736.881608 but for some reason converting the utcnow() gives 2 hours backward again.
So for some reason I get another 2 hours withdrawal when taking timestamp of a utcnow() created datetime object. I am currently running a macbook m1 pro, with Timezone Norway (+1, +2 atm with daylight), and python 3.9.12
So can this be the arm architecture messing up things or is it just not recommended to use the utcnow() and then convert to timestamp?
The answer to your question is managing timezones (TZ). When you create a datetime instance with now() or utcnow(), it does not store info about TZ. And, according to python docs for utcnow() (bolding by author):
Return the current UTC date and time, with tzinfo None.
This is like now(), but returns the current UTC date and time, as a naive datetime object. An aware current UTC datetime can be obtained by calling datetime.now(timezone.utc). See also now().
Warning: Because naive datetime objects are treated by many datetime methods as local times, it is preferred to use aware datetimes to represent times in UTC. As such, the recommended way to create an object representing the current time in UTC is by calling datetime.now(timezone.utc).
This means that, although you received time for UTC TZ with utcnow(), since no TZ info is stored (naive datetime object), python thinks of it as a local time. And, when converting it to timestamp, will add/subtract time difference once again. Proof for this weird behaviour may be found in python docs for timestamp() method:
Naive datetime instances are assumed to represent local time
The reason actually is the one, you stated in the title of the question, not the ARM architecture
I'm having a little bit of a problem here. My system lets me
pip install calendar
but for some reason it doesn't recognize it when importing it in my script.
Whereas for datetime, the module datetime.datetime gives me an error saying that
there is no attribute datetime in datetime.
And datetime.date wants me to feed it a datetime.datetime object, therefore it doesn't let me input strings, lists, ints, or whatever.
Does anyone know another possible way to get the current weekday, or how to fix one of the above?
Thanks
using time.
from time import time, localtime, strftime
x=localtime(time())
strftime("%A",x) # 'Tuesday'
It looks like your most recent errors are caused by the same thing causing the original error with the datetime module.
there is no attribute datetime in datetime.
Is likely the same as the error caused by this line hoursMinsSecs = time.strftime('%H, %M, %S')
These errors are caused because both the datetime and time modules have objects with the same name as the module. (time.time and datetime.datetime). Therefore, how you import the modules or objects becomes very important.
In the time example, your import statement is:
from time import time, localtime, strftime
As a result, the time object has been imported into your namespace and not the time module. Therefore, when you try to run time.strftime('%H, %M, %S') you get an error that strftime isn’t an attribute of the time object.
Instead, since you already imported strftime, just call that directly and do not qualify it with time. (i.e. strftime('%H, %M, %S'))
For your datetime example, you probably had the import statement from datetime import datetime, but somewhere in your code used datetime.datetime
I can create a timezone specific datetime object like this
import datetime
d = datetime.datetime.now().astimezone()
Result is
datetime.datetime(2018, 4, 2, 15, 12, 2, 807451, tzinfo=datetime.timezone(datetime.timedelta(0, 7200), 'CEST'))
It looks like that tzinfo is represented by two values/attributes: A timedelta and a string. But how can I access them?
I would like to do something like this
d.tzinfo.delta
d.tzinfo.name
I need this informations to be able to (de)serialize the datetime to and from JSON.
I don't want to use third-party packages for such solutions.
tzinfo in this case is an instance of the datetime.timezone() class:
The timezone class is a subclass of tzinfo, each instance of which represents a timezone defined by a fixed offset from UTC.
You can use the tzinfo.utcoffset() and tzinfo.utcname() methods to access the delta and name. For timezone() instances the argument each of these take is ignored, but normally you'd pass in the datetime instance they are attached to:
d.tzinfo.utcoffset(d)
d.tzinfo.utcname(d)
You'd usually call these on the datetime.datetime instance, which has the same methods (but which take no arguments) and these will then handle passing in the right argument to the methods on the contained tzinfo attribute.
Demo:
>>> import datetime
>>> d = datetime.datetime.now().astimezone()
>>> d.utcoffset()
datetime.timedelta(seconds=7200)
>>> d.tzname()
'CEST'
>>> d.tzinfo.utcoffset(d)
datetime.timedelta(seconds=7200)
>>> d.tzinfo.utcoffset(d) is d.utcoffset() # they are the same object
True
The datetime.timezone() subclass is just one implementation of a tzinfo time zone, 3rd-party libraries like pytz offer their own, and the utcoffset() and tzname() return values may well vary for timezones with historical information attached.
You're asking about datetime.tzinfo, which is an abstract base class, as documented here.
datetime comes with an implementation of the tzinfo abstract base class called datetime.timezone, which is documented here.
Just below that last link are the docs on timezone.utcoffset and timezone.utcname, which are ways to access the properties you asked about on the tzinfo if it is a timezone. However, this is not the only implementation of that abstract class. If you are using the pytz timezone, for example, then you'll need to read the docs on that instead.
I need some clarification on how module and class level imports are handled when coexisting in the same namespace. See the following examples:
Works:
import datetime
print datetime.datetime.utcnow()
Fails:
from datetime import datetime
print datetime.datetime.utcnow()
Error: AttributeError: type object 'datetime.datetime' has no
attribute 'datetime'
Works:
from datetime import datetime # Is this ignored?
import datetime
print datetime.datetime.utcnow()
What exactly is happening in the 3rd example? Is the second module import replacing the class-specific first import? Does this mean that module and class level imports shouldn't be mixed in the same namespace?
There is no priority is such. The outcome is determined by the order in which import statements are executed, as follows.
If you try to import several things called X into your namespace, each import would rebind X to whatever it's importing.
Therefore at the end it will be last import that'll be in effect as far as the name X in concerned.
This is precisely what happens in your third example:
from datetime import datetime # This isn't ignored, but the name is immediately rebound
# by the next line
import datetime # Rebinds the name
Some of the IDE's that support python would give you the explanation, but yes, you're redefining (overwriting, replacing) the import in the 3rd example. Each name within a file is distinct. If you need access to a module and a class that share a name you need to use something like from datetime import datetime as dt.
An import is really just an assignment: it sets a name in your current namespace. So, in the third case, you set the name datetime as equal to the datetime class, then immediately reassign it to the datetime module.
There is no reason to do it like this:
from datetime import datetime
print datetime.datetime.utcnow()
this code, on the other hand, would do exactly what you want it to:
from datetime import datetime
print datetime.utcnow()
Your first example imports the datetime module and provides a datetime label in the local namespace representing it, then calls the utcnow() method of the datetime object belonging to the datetime module. The second adds the datetime.datetime object (not the module) to the local namespace with the label datetime, but the datetime object has no attribute datetime, so you get the exception. The third example assigns the datetime.datetime object to the label of that name in the namespace, then reassigns the label to the datetime module. So ignoring the mechanics of import that are irrelevant to this question (basically, adding modules to sys.modules if they are not there yet), what you have is equivalent to:
datetime = sys.modules['datetime']
datetime.datetime.utcnow()
then
datetime = sys.modules['datetime'].datetime
datetime.datetime.utcnow()
then
datetime = sys.modules['datetime'].datetime
datetime = sys.modules['datetime']
datetime.datetime.utcnow()
Is there a way I can obtain a datetime aware object out of a string in Python using only the standard library modules ?
I know that I can use dateutil.parser.parse, but unfortunately that's not a good enough reason to add it as a dependency to my project. I already have the mx.DateTime module as a dependency, buuttttt:
>>> dateutil.parser.parse('2011-10-24T06:51:47-07:00')
datetime.datetime(2011, 10, 24, 6, 51, 47, tzinfo=tzoffset(None, -25200))
>>> mx.DateTime.ISO.ParseDateTimeUTC('2011-10-24T06:51:47-07:00')
<mx.DateTime.DateTime object for '2011-10-24 13:51:47.00' at 29c7e48>
the ParseDateTimeUTC fails to detect the offset, even though in its documentation says that:
Returns a DateTime instance in UTC reflecting the given ISO
date. A time part is optional and must be delimited from the
date by a space or 'T'. Timezones are honored.
mx.DateTime.ISO.ParseDateTimeUTC is doing the right thing - it is applying the specified timezone to adjust the time to UTC. The resulting UTC time doesn't have a timezone because it isn't a local time anymore.
The standard Python library doesn't contain any concrete timezone classes according to the documentation:
tzinfo is an abstract base clase, meaning that this class should not
be instantiated directly. You need to derive a concrete subclass, and
(at least) supply implementations of the standard tzinfo methods
needed by the datetime methods you use. The datetime module does not
supply any concrete subclasses of tzinfo.
I've always been surprised that they didn't at least include a class for UTC, or a generic implementation like dateutil's tzoffset.