I'd like to query my DB for all records posted on a particular day (e.g. today between 00:00 and 23:59:59) given a datetime.datetime timestamp such as datetime.datetime(2010, 12, 21, 17, 59, 43, 85335).
What's the best method to calculate the start and end datetime.datetime instances, please? I'd like to end up with something like this:
>>> timestamp = datetime.datetime(2010, 12, 21, 17, 59, 43, 85335)
>>> # do something with timestamp to get start_date and end_date
>>> start_date
datetime.datetime(2010, 12, 21, 0, 0, 0, 0)
>>> end_date
datetime.datetime(2010, 12, 21, 23, 59, 59, 0)
Thanks, HC
Ah, found what I want. I struggle with datetime every time.
>>> timestamp = datetime.datetime.now()
>>> timestamp
datetime.datetime(2010, 12, 21, 18, 31, 37, 900795)
>>> timestamp.replace(hour=0, minute=0, second=0, microsecond=0)
datetime.datetime(2010, 12, 21, 0, 0)
If it's just calculating a day, then what you have is fine. Just use the day and then put the hour as 0:00 and 23:59 respectively.
If you want to get the start and end times of a month, that gets a lot more complicated since months have different days. For something like that you could use this module
http://niemeyer.net/python-dateutil
timedelta sounds just like what you need.
http://docs.python.org/library/datetime.html#timedelta-objects
from datetime import datetime, date
date.today() - timedelta(days=7)
Will give you 7 days from today.
Related
I have an object of <class 'datetime.datetime'>.
obj = datetime.datetime(2021, 6, 28, 2, 15, tzinfo=<FixedOffset '-07:00'>)
The time zone is PDT(offset -7:00). I need to convert it to UTC.
So if the object has datetime as 2021-05-02 10:00:00.000 -07:00.
It should be changed to 2021-05-02 17:00:00.000 +00:00.
How to achieve this in python?
Try the following, using .astimezone():
>>> import datetime
>>> obj = datetime.datetime.now()
>>> obj
datetime.datetime(2021, 7, 19, 13, 18, 26, 601212)
>>> obj.astimezone(tz=datetime.timezone.utc)
datetime.datetime(2021, 7, 19, 17, 18, 26, 601212, tzinfo=datetime.timezone.utc)
use time delta
bj = dt.datetime(2021,6,28,10,0)+dt.timedelta(hours=7)
pd.to_datetime(bj)
I need to set the time value of detatime objects to 00:00, so I can easily compare two 'dates'
Now I do:
extracted_start_date = datetime.strptime(extracted_start_date.strftime('%Y-%m-%d'), '%Y-%m-%d')
so I have my datetime object
$ datetime.datetime(2021, 3, 18, 11, 13, 53, 782088),
I extract the date string strftime('%Y-%m-%d')
$ '2021-03-18'
and put this back into a datetime object now wch has time 00:00
$ datetime.datetime(2021, 3, 18, 0, 0)
This seems quite elaborate, is there a more efficient way, or is it OK like this?
datetime.datetime objects have method date which return datetime.date instance and these might be used for day-based comparison, consider following example:
import datetime
d1 = datetime.datetime(2021, 3, 17, 9, 0, 0) # yesterday 9:00
d2 = datetime.datetime(2021, 3, 18, 9, 0, 0) # today 9:00
d3 = datetime.datetime(2021, 3, 18, 12, 0, 0) # today 12:00
print(d1.date() == d2.date())
print(d2.date() == d3.date())
output:
False
True
You could use the replace method instead.
from datetime import datetime
d = datetime(2021, 3, 18, 11, 13, 53, 782088)
d.replace(hour=0, minute=0, second=0, microsecond=0)
> datetime.datetime(2021, 3, 18, 0, 0)
How do you get a valid timedelta instance when differencing datetimes with different timezones in Python? I'm finding the timedelta is always 0 if the timezones are different.
>>> from dateutil.parser import parse
>>> dt0=parse('2017-02-06 18:14:32-05:00')
>>> dt0
datetime.datetime(2017, 2, 6, 18, 14, 32, tzinfo=tzoffset(None, -18000))
>>> dt1=parse('2017-02-06 23:14:32+00:00')
>>> dt1
datetime.datetime(2017, 2, 6, 23, 02, 12, tzinfo=tzutc())
>>> (dt1-dt0).total_seconds()
0.0
This doesn't make any sense to me. I would have thought that Python's datetime class would be smart enough to normalize both values to UTC internally, and then return a timedelta based on those values. Or throw an exception. Instead it returns 0, implying both datetimes are equal, which clearly they're not. What am I doing wrong here?
You are confused about what the timezone means; the two times you gave are identical, so of course their difference is zero. I can duplicate your results, except that I don't have the discrepancy between the second string and second datetime that you have:
>>> from dateutil.parser import parse
>>> dt0=parse('2017-02-06 18:14:32-05:00')
>>> dt0
datetime.datetime(2017, 2, 6, 18, 14, 32, tzinfo=tzoffset(None, -18000))
>>> dt1=parse('2017-02-06 23:14:32+00:00')
>>> dt1
datetime.datetime(2017, 2, 6, 23, 14, 32, tzinfo=tzutc())
>>> (dt1-dt0).total_seconds()
0.0
But watch what happens when I convert dt0 to UTC. The time gets adjusted by the 5 hour timezone difference, and it becomes identical to the second.
>>> dt0.astimezone(dt1.tzinfo)
datetime.datetime(2017, 2, 6, 23, 14, 32, tzinfo=tzutc())
I am attempting to build a program to handle alerts. I want it to be able to handle specific dates like 8/23/2015 7:00 and relative dates like 5 days and 7 hours from now. specific dates are fine but for relative dates if I try and just add 5 days and 7 hours to the date time it can overflow the values intended for that spot
import datetime
dt = datetime.datetime.now()
dayslater = 5
hourslater = 7
minuteslater = 30
alarmTime = datetime.datetime(dt.year, dt.month, dt.day + dayslater,
dt.hour + hourslater,
dt.minute + minuteslater, 0,0)
this is fine sometimes but if dayslater was 40 days it would overflow the value. I did set up a simple
if hours >= 24:
hours -= 24
days++
however this won't work for overflowing months whose length in days isn't consistent.
Don't. Dates are hard, and it's very easy to get it wrong.
Instead, use timedelta:
In [1]: from datetime import datetime, timedelta
In [2]: dt = datetime.now()
In [3]: dt
Out[3]: datetime.datetime(2015, 7, 23, 15, 2, 55, 836914)
In [4]: alarmTime = dt + timedelta(days=5, hours=7, minutes=30)
In [5]: alarmTime
Out[5]: datetime.datetime(2015, 7, 28, 22, 32, 55, 836914)
Use a datetime.timedelta() object and leave calculations to the datetime library:
import datetime
delta = datetime.timedelta(days=dayslater, hours=hourslater, minutes=minuteslater)
alarmTime = datetime.datetime.now() + delta
Demo:
>>> import datetime
>>> dt = datetime.datetime.now()
>>> dayslater = 5
>>> hourslater = 7
>>> minuteslater = 30
>>> delta = datetime.timedelta(days=dayslater, hours=hourslater, minutes=minuteslater)
>>> delta
datetime.timedelta(5, 27000)
>>> dt
datetime.datetime(2015, 7, 23, 21, 4, 59, 987926)
>>> dt + delta
datetime.datetime(2015, 7, 29, 4, 34, 59, 987926)
Note how the hours carried over to the next day (from 21:04 to 04:34), and thus the date went from the 23rd to the 29th. I did not have to worry about 'overflow' here.
This continues to work at month boundaries, at year boundaries, and in leap years, with February 29th:
>>> datetime.datetime(2015, 7, 26, 22, 42) + delta
datetime.datetime(2015, 8, 1, 6, 12)
>>> datetime.datetime(2015, 12, 26, 22, 42) + delta
datetime.datetime(2016, 1, 1, 6, 12)
>>> datetime.datetime(2016, 2, 23, 22, 42) + delta
datetime.datetime(2016, 2, 29, 6, 12)
I'm probably missing something about timezones:
>>> import datetime, pytz
>>> date = datetime.datetime(2013,9,3,16,0, tzinfo=pytz.timezone("Europe/Paris"))
>>> date.astimezone(pytz.UTC)
datetime.datetime(2013, 9, 3, 15, 51, tzinfo=<UTC>)
I was expecting
datetime.datetime(2013, 9, 3, 15, 00, tzinfo=<UTC>)
Can anyone explain me where these 51 minutes come from?
Thanks,
Jean-Philippe
The UTC offset gives (date.tzinfo.utcoffset(date)):
datetime.timedelta(0, 540)
This is 540 seconds or 9 minutes.
In France the switch to UTC was made on March 11, 1911 and the clocks were turned back 9 minutes and 21 seconds (source 1, source 2):
Until 1911, Paris was 9 minutes and 21 seconds off UTC.
You can also see it here (Paris time in 1911) where the time goes from March 11, 12:01:00 AM to March 10, 11:51:39 PM.
Read the note at the very begining of pytz documentation ; use .localize() method to create timezone-aware datetime object:
import datetime
import pytz
naive_dt = datetime.datetime(2013,9,3,16,0)
dt = pytz.timezone("Europe/Paris").localize(naive_dt, is_dst=None)
to_s = lambda d: d.strftime('%Y-%m-%d %H:%M:%S %Z%z')
print(to_s(dt))
print(to_s(dt.astimezone(pytz.utc)))
Output
2013-09-03 16:00:00 CEST+0200
2013-09-03 14:00:00 UTC+0000
I don't know why you are expecting 15:00 UTC here.
Thanks Simeon for your answer. It made me realize how shallow is my understanding of all of this. The following experimentations lost me a little more...
>>> import datetime, pytz
>>> date_paris = datetime.datetime(2013,9,3,16,0, tzinfo=pytz.timezone("Europe/Paris"))
>>> date_utc = datetime.datetime(2013,9,3,16,0, tzinfo=pytz.utc)
>>> date_paris.astimezone(pytz.utc)
datetime.datetime(2013, 9, 3, 15, 51, tzinfo=<UTC>)
>>> date_utc.astimezone(pytz.timezone("Europe/Paris"))
datetime.datetime(2013, 9, 3, 18, 0, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)
Why this 9 minutes offset shows up when converting in one direction but not the other? The following piece of code concentrate all disappointment:
>>> date_paris
datetime.datetime(2013, 9, 3, 16, 0, tzinfo=<DstTzInfo 'Europe/Paris' PMT+0:09:00 STD>)
>>> date_paris.astimezone(pytz.utc).astimezone(pytz.timezone("Europe/Paris"))
datetime.datetime(2013, 9, 3, 17, 51, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)