from datetime import datetime as dt
fmt = '%a %d %b %Y %H:%M:%S %z'
for i in range(int(input())):
print(int(abs((dt.strptime(input(), fmt) -
dt.strptime(input(), fmt)).total_seconds())))
Why are we able to call the total_seconds() method without importing the timedelta class? As total_seconds() is a method in timedelta class.
When you subtract 2 datetime objects, the result is timedelta object.
from datetime import datetime
dt1 = datetime.now()
dt2 = datetime.now()
value = dt2 - dt1
print(type(value))
Output is:
<class 'datetime.timedelta'>
You are right, as you are subtracting two datetime objects. As per the method __sub__ it returns timedelta object (See below). And as you said total_seconds is method of timedelta class.
def __sub__(self, other):
"Subtract two datetimes, or a datetime and a timedelta."
if not isinstance(other, datetime):
if isinstance(other, timedelta):
return self + -other
return NotImplemented
days1 = self.toordinal()
days2 = other.toordinal()
secs1 = self._second + self._minute * 60 + self._hour * 3600
secs2 = other._second + other._minute * 60 + other._hour * 3600
base = timedelta(days1 - days2,
secs1 - secs2,
self._microsecond - other._microsecond)
if self._tzinfo is other._tzinfo:
return base
myoff = self.utcoffset()
otoff = other.utcoffset()
if myoff == otoff:
return base
if myoff is None or otoff is None:
raise TypeError("cannot mix naive and timezone-aware time")
return base + otoff - myoff
The import machinery works at 2 levels. First it loads and execute the module. So if it contains other imports, they are loaded (and executed) too. That means that the instruction
from datetime import datetime as dt
actually loads datetime (to be able to access datetime.datetime), and datetime.datetime. Because of that, datetime.timedelta is loaded too. In fact, it is required from datetime.datetime to be able to define the difference between 2 datetime.datetime objects. So everything has been loaded by the Python interpretor.
The second level imports symbols in the current namespace. At this level,
from datetime import datetime as dt
only creates the dt symbol in the namespace. That means that if you use directly datetime in your code, you will get a NameError because the symbol is undefined, but if you examine sys.module, you will find that it is there...
Related
I have the following code:
import datetime
from datetime import datetime as dt
def ceil_dt(dt, delta):
return dt + (dt.min - dt) % delta
NextInterval5m = ceil_dt(now, timedelta(minutes=5))
unixtime5m = dt.fromtimestamp(NextInterval5m)
The problem is that i keep getting the following error:
TypeError: an integer is required (got type datetime.datetime)
Can someone help me out on this? I don't understand to what i am supposed to convert NextInterval5m in order to make it work. I'm trying to convert NextInterval5m to an Unix timestamp
You should be able to convert it into a unix timestamp by using .timestamp() on a datetime.datetime object. However, this function is exclusive to Python 3. If you need something for python 2, you can use .total_seconds() which requires a datetime.time_delta object instead.
Documentation: https://docs.python.org/3.8/library/datetime.html#datetime.datetime.timestamp
If you are using python 3.3+, use .timestamp()
import datetime
from datetime import datetime as dt
from datetime import timedelta
def ceil_dt(dt, delta):
return dt + (dt.min - dt) % delta
now = dt.now()
NextInterval5m = ceil_dt(now, timedelta(minutes=5))
unixtime5m = NextInterval5m.timestamp()
print(unixtime5m)
Output:
1596926400.0
OR
import datetime
from datetime import datetime as dt
from datetime import timedelta
def ceil_dt(dt, delta):
return dt + (dt.min - dt) % delta
now = dt.now()
NextInterval5m = ceil_dt(now, timedelta(minutes=5))
unixtime5m = NextInterval5m.timestamp()
print((NextInterval5m - datetime.datetime(1970,1,1)).total_seconds())
can you tell me why it doesn't translate the date into numbers?
import datetime
from datetime import datetime
from datetime import timedelta
from django.db import models
def end_date():
return datetime.date.today() + timedelta(days=7)
def convert_date_str(add_date):
return datetime.strftime(add_date, "%m/%m/%Y")
class add(models.Model):
add_date = models.DateField('Дата додавання', auto_now_add=True)
end_date = models.DateField('Дата здачі', default=end_date)
as I do not output from the DB string month
First of all, strftime needs to be called on a datetime object so you need to enclose your addition statement in brackets.
from datetime import datetime, timedelta
def end_date():
return (datetime.today() + timedelta(days=7)).strftime("%d %B, %Y")
strptime is under datetime.datetime so you are going too deep. In any case, your second function doesn't make sense. You can only strptime from a string, not a datetime object. You also shouldn't use the same function and variable names. If you are trying to translate a datestring like 31/01/1999 to a datetime object, you can do
def convert_to_datetime(date_str):
return datetime.strptime(date_str, '%d/%m/%Y')
Your function names should also be more descriptive because at the moment I don't think any of them describes its actual functionality.
You're probably getting an Attribute error because timedelta has no strftime method. what you want is:
def end_date():
# add date object to timedelta first then get string
return (datetime.date.today() + timedelta(days=7)).strftime("%d %B, %Y")
second, strptime method takes a string and makes a datetime object. add_date is a date object not a string
def add_date():
add_date = datetime.date.today() # <-- this should be a string for strptime to work
# whats dt in your example?, also strptime argument must be a string
data_object = datetime.datetime.strptime(add_date, "%d %B, %Y").date()
return data_object
Dateutil's timedelta object appears to have a custom __str__ method:
In [1]: from datetime import timedelta
In [2]: td = timedelta(hours=2)
In [3]: str(td)
Out[3]: '2:00:00'
What I'd like to do is re-create a timedelta object from its string representation. As far as I can tell, however, the datetime.parser.parse method will always return a datetime.datetime object (cf. https://dateutil.readthedocs.io/en/stable/parser.html):
In [4]: import dateutil.parser
In [5]: dateutil.parser.parse(str(td))
Out[5]: datetime.datetime(2016, 11, 25, 2, 0)
The only way I see now to do this is to, in the parlance of Convert a timedelta to days, hours and minutes, 'bust out some nauseatingly simple (but verbose) mathematics' to obtain the seconds, minutes, hours, etc., and pass these back to the __init__ of a new timedelta. Or is there perhaps a simpler way?
Use datetime.strptime to convert a string to timedelta.
import datetime
td = datetime.timedelta(hours=2)
# timedelta to string
s = str(td) # 2:00:00
# string to timedelta
t = datetime.datetime.strptime(s,"%H:%M:%S")
td2 = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second)
The module pytimeparse, which was inspired by How to construct a timedelta object from a simple string, seems to do the heavy lifting by returning the number of seconds. I just put a wrapper around it which returns a timedelta object with the same number of seconds:
#!/usr/bin/env python3.5
import datetime
import pytimeparse
import unittest
def reconstruct_timedelta(td_string):
seconds = pytimeparse.parse(td_string)
return datetime.timedelta(seconds=seconds)
class TestReconstruction(unittest.TestCase):
def test_reconstruct_timedelta_is_inverse_of_str(self):
td = datetime.timedelta(weeks=300, days=20, hours=3, minutes=4, milliseconds=254, microseconds=984)
td_reconstructed = reconstruct_timedelta(str(td))
self.assertTrue(td == td_reconstructed)
if __name__ == "__main__":
unittest.main()
As you can see from the test, the reconstructed timedelta object is the same as the original one, even when it is initialized with an arbitrary number if milliseconds and microseconds.
How about use pickle? You may refer to https://docs.python.org/2/library/pickle.html
Serialize the time delta object, and get back the object later.
import pickle
tdi = pickle.dumps(td)
tdo = pickle.loads(tdi) # will have the time delta object
str(tdo)
I need to convert a datetime object with microsecond resolution to a timestamp, the problem is that I don't get the same timestamp second's resolution.
For example the timestamp that I pass as an argument is 1424440192 and I get in return 1424429392.011750, why is this?, I Only changed microsecond value of the datetime object, so I expect to change only values after the dot.
PD: In this example I'm only simulating one timestamp.
from datetime import datetime, timedelta
def totimestamp(dt, epoch=datetime(1970,1,1)):
td = dt - epoch
return td.total_seconds()
#return (td.microseconds + (td.seconds + td.days * 24 * 3600) *
#10**6) / 1e6
timestamp_pc = 1424440192
tm = datetime.fromtimestamp(timestamp_pc)
new_tm = tm.replace(microsecond = 11750)
print tm
print new_tm
print timestamp_pc
print "%f " %(totimestamp(new_tm))
I get it.
I changed
tm = datetime.fromtimestamp(timestamp_pc)
for
tm = datetime.utcfromtimestamp(timestamp_pc)
and now timestamp are identical.
From the fromtimestamp documentation:
If optional argument tz is None or not specified, the timestamp is converted to the platform’s local date and time, and the returned datetime object is naive.
Since your totimestamp function does not do the same timezone adjustment in reverse, the time is wrong by your time zone offset.
It looks like this has been covered somewhat in other questions, but I'm still fairly confused on how to actually do this. My lack of experience isn't helping much with that.
I have two DateTimeProperties - StartTime and EndTime. I'm subtracting StartTime from EndTime to get the Duration. From my previous question (thank you to all that answered!) it looks like this operation is producing a timedelta.
There doesn't seem to be an easy way to store timedelta directly in the GAE datastore, so this means I need to convert it either to an int in milliseconds, to a float in seconds or to time.
I will need to do other calculations on this later as well, such as figuring out avg. duration. Based on that, int seems to make the most sense to me right now.
What's the best way to do this or is there a tutorial I can play with?
Thank you!
To make this as easy as possible to work with, there's two steps: Converting the timedelta to an int or a float, and storing it in the datastore. First things first, converting a timedelta to a microtime:
def timedelta_to_microtime(td):
return td.microseconds + (td.seconds + td.days * 86400) * 1000000
You don't have to do the conversion yourself, though - you can define a custom datastore property, which will allow you to store timedeltas directly to your model:
class TimeDeltaProperty(db.Property):
def get_value_for_datastore(self, model_instance):
value = self.__get__(model_instance, model_instance.__class__)
if value is not None:
return timedelta_to_microtime(value)
def make_value_from_datastore(self, value):
if value is not None:
return datetime.timedelta(microseconds=value)
Now you can use this property like any other:
class MyModel(db.Model):
td = TimeDeltaProperty(required=True)
entity = MyModel(td=datetime.datetime.now()-some_datetime)
key = entity.put()
entity = db.get(key)
print entity.td
If you're going to store it as a datetime (which I agree is a good idea), I'd extend the DateTimeProperty - then you get various bits of parsing and validation for free.
Also, storing as timedelta as a datetime can be much easier than the other methods given here, by storing it as a datetime some distance from a reference datetime, such that the difference represents the timedelta. This is really easy thanks to the operator overloading the datetime module gives us.
from datetime import datetime, timedelta
from google.appengine.ext import db
class TimeDeltaProperty(db.DateTimeProperty):
# Use a reference datetime half way between the min and max possible
# datetimes, so that we can support both +ve and -ve timedeltas
ref_datetime = (datetime.max - datetime.min) / 2 + datetime.min
def get_value_for_datastore(self, model_instance):
# Get the timedelta instance assigned to this property
td = super(TimeDeltaProperty, self).get_value_for_datastore(model_instance)
if td is not None:
# datetime + timedelta = datetime
return self.ref_datetime + td
def make_value_from_datastore(self, dt):
if dt is not None:
# datetime - datetime = timedelta
return dt - self.ref_datetime
And here's an equivalent implementation for the NDB API, if you're that way inclined:
from datetime import datetime, timedelta
from google.appengine.ext import ndb
class TimeDeltaProperty(ndb.DateTimeProperty):
# Use a reference datetime half way between the min and max possible
# datetimes, so that we can support both +ve and -ve timedeltas
ref_datetime = (datetime.max - datetime.min) / 2 + datetime.min
def _validate(self, value):
if not isinstance(value, timedelta):
raise TypeError('expected a datetime.timedelta, got %r' % value)
def _to_base_type(self, value):
# datetime + timedelta = datetime
return self.ref_datetime + td
def _from_base_type(self, value):
# datetime - datetime = timedelta
return dt - self.ref_datetime
Accuracy
A timedelta in Python can handle deltas of roughly +/-2.7 million years. However, a datetime only covers a range of about 10,000 years. To store a greater timedelta in a datetime, you'll have to do some shifting and sacrifice some accuracy.
The approach above limits timedeltas to half this range - about +/-5000 years, because of the choice of reference datetime.
If you know your timedelta will always be positive, you can use ref_datetime = datetime.min (or if you know it'll always be negative you can use ref_datetime = datetime.max) to get the full range of about 10,000 years.
import pickle
import datetime
...
delta = end_time - start_time
for_storage = pickle.dumps(delta)
#now you have a string representation of your timedelta object that you can store
#sometime later...
delta = pickle.loads(from_storage)
You'll still need to convert the delta to a time resolution of your choice using the days, mins, seconds, and microseconds attributes of the time delta.
This ultimately worked:
delta = StartTime - EndTime
event_record.Duration = int((delta.microseconds)/1000)
basically, needed to get microseconds out of the timedelta and convert it to milliseconds.