I have time defined in the following format: "%A %H:%M:%S" i.e "Monday 06:00:00"
Now, using the above format, I define a time window:
"Monday 06:00:00" - "Monday 18:00:00"
I now want to check if the current time falls within the time window or not. To do that, I am using the datetime utility.
import datetime
# current time in str
current_time = datetime.datetime.strftime(datetime.datetime.now(),'%A %H:%M:%S')
# convert to datetime object
current_time = datetime.datetime.strptime(current_time, '%A %H:%M:%S')
# print current_time produces: 1900-01-01 19:13:53
# and day of week information is lost
However, the moment, I convert the current_time to a datetime object, the day of the week information is lost.
What's the best way to compare time windows that includes day-of-week in Python?
BTW: I want the time window to be repeated in the future. For eg, "Monday 06:00 - Tuesday 05:00" would apply to all weeks in the future.
datetime would know nothing about which monday you're talking about. There have been 1000's since the epoch.
I suggest you look into the dateutil package. It applies "human-ish" semantics:
>>> import dateutil.parser
>>> dateutil.parser.parse('Monday')
datetime.datetime(2014, 2, 3, 0, 0)
>>> dateutil.parser.parse('Monday 18:30:00')
datetime.datetime(2014, 2, 3, 18, 30)
Note how it assumes that Monday means today (it's Monday). And Tuesday and Sunday (below) mean this coming Tuesday, Sunday:
>>> dateutil.parser.parse('Tuesday 18:30:00')
datetime.datetime(2014, 2, 4, 18, 30)
>>> dateutil.parser.parse('Sunday 18:30:00')
datetime.datetime(2014, 2, 9, 18, 30)
To take this further one take a look at the rrule module/class in dateutil. And the built-in calendar module. For example, with rrule I can do:
next_five = rrule.rrule(
rrule.WEEKLY,
count=5,
dtstart=dateutil.parser.parse('Sunday 18:30:00'),
)
This returns an iterator of the next 5 weeks starting at 6:30pm Sunday. The iterator will produce
[datetime.datetime(2014, 2, 5, 18, 30),
datetime.datetime(2014, 2, 12, 18, 30),
datetime.datetime(2014, 2, 19, 18, 30),
datetime.datetime(2014, 2, 26, 18, 30),
datetime.datetime(2014, 3, 5, 18, 30)]
This should get you going on the final solution.
In my experience Datetime objects are YYYY:MM:DD HH:MM:SS (more or less). The day of week can be derived from that object using datetime's weekday() - see http://docs.python.org/2/library/datetime.html#datetime.date.weekday
You can solve your problem using greater/less than "<" and ">" operators for datetime evaluation. Here is a proof for simple comparison http://pastebin.com/miTUW9nF
Your logic would be (paraphrased): "if Xtime > windowstart and Xtime < windowend then Xtime is in window"
Datetime compares down to the second, my example is now and (now-10 days), that should cover your needs.
Related
Have two data sets with different time format. One in epcoh time, seconds from 1/1/1970, and the other hours since 1/1/1900. Need to convert the first to the second one. How can I do that in python ?
Thanks
So, for starters, here are the necessary tools:
from datetime import datetime, timezone, timedelta
Then you need to establish the starting time:
atmos_epoch = datetime(1900, 1, 1, 0, 0, tzinfo=timezone.utc)
Then you can work with deltas to that time:
>>> d = datetime.now(timezone.utc) - atmos_epoch
>>> d
datetime.timedelta(days=43893, seconds=28215, microseconds=982930)
>>> d.total_seconds() / 60 / 60
1053439.8377730362
That last value is the difference in hours.
You can add deltas to that epoch timestamp:
>>> atmos_epoch + timedelta(hours=1000000)
datetime.datetime(2014, 1, 29, 16, 0, tzinfo=datetime.timezone.utc)
The other thing you talk about, seconds since 1970, are simply UNIX timestamps, which you can work with easily:
>>> datetime.now().timestamp()
1583395060.91666
>>> datetime.fromtimestamp(1500000000)
datetime.datetime(2017, 7, 14, 4, 40)
Now you have a way to convert from both values to datetime objects and from datetime objects to either value.
How can I create a date time object for 9:00 AM UTC to use for comparison with the current utc time?
new_date = datetime.datetime(2019, 12, 2, 10, 24, 34, 198130)
I want to do it without the year, minutes and seconds.
If you don't need the date part of it, use datetime.time:
import datetime
nine_am = datetime.time(9)
if datetime.datetime.utcnow().time() > nine_am:
...
I have a date string and want to convert it to the date type:
I have tried to use datetime.datetime.strptime with the format that I want but it is returning the time with the conversion.
when = alldates[int(daypos[0])]
print when, type(when)
then = datetime.datetime.strptime(when, '%Y-%m-%d')
print then, type(then)
This is what the output returns:
2013-05-07 <type 'str'>
2013-05-07 00:00:00 <type 'datetime.datetime'>
I need to remove the time: 00:00:00.
print then.date()
What you want is a datetime.date object. What you have is a datetime.datetime object. You can either change the object when you print as per above, or do the following when creating the object:
then = datetime.datetime.strptime(when, '%Y-%m-%d').date()
If you need the result to be timezone-aware, you can use the replace() method of datetime objects. This preserves timezone, so you can do
>>> from django.utils import timezone
>>> now = timezone.now()
>>> now
datetime.datetime(2018, 8, 30, 14, 15, 43, 726252, tzinfo=<UTC>)
>>> now.replace(hour=0, minute=0, second=0, microsecond=0)
datetime.datetime(2018, 8, 30, 0, 0, tzinfo=<UTC>)
Note that this returns a new datetime object -- now remains unchanged.
>>> print then.date(), type(then.date())
2013-05-07 <type 'datetime.date'>
To convert a string into a date, the easiest way AFAIK is the dateutil module:
import dateutil.parser
datetime_object = dateutil.parser.parse("2013-05-07")
It can also handle time zones:
print(dateutil.parser.parse("2013-05-07"))
>>> datetime.datetime(2013, 5, 7, 1, 12, 12, tzinfo=tzutc())
If you have a datetime object, say:
import pytz
import datetime
now = datetime.datetime.now(pytz.UTC)
and you want chop off the time part, then I think it is easier to construct a new object instead of "substracting the time part". It is shorter and more bullet proof:
date_part datetime.datetime(now.year, now.month, now.day, tzinfo=now.tzinfo)
It also keeps the time zone information, it is easier to read and understand than a timedelta substraction, and you also have the option to give a different time zone in the same step (which makes sense, since you will have zero time part anyway).
For me, I needed to KEEP a timetime object because I was using UTC and it's a bit of a pain. So, this is what I ended up doing:
date = datetime.datetime.utcnow()
start_of_day = date - datetime.timedelta(
hours=date.hour,
minutes=date.minute,
seconds=date.second,
microseconds=date.microsecond
)
end_of_day = start_of_day + datetime.timedelta(
hours=23,
minutes=59,
seconds=59
)
Example output:
>>> date
datetime.datetime(2016, 10, 14, 17, 21, 5, 511600)
>>> start_of_day
datetime.datetime(2016, 10, 14, 0, 0)
>>> end_of_day
datetime.datetime(2016, 10, 14, 23, 59, 59)
If you specifically want a datetime and not a date but want the time zero'd out you could combine date with datetime.min.time()
Example:
datetime.datetime.combine(datetime.datetime.today().date(),
datetime.datetime.min.time())
You can use simply pd.to_datetime(then) and pandas will convert the date elements into ISO date format- [YYYY-MM-DD].
You can pass this as map/apply to use it in a dataframe/series too.
You can usee the following code:
week_start = str(datetime.today() - timedelta(days=datetime.today().weekday() % 7)).split(' ')[0]
I have a string:
t = "2017-01-05T14:23:33.986-0500"
I need to convert it to a Python date.
I used:
t_obj = datetime.strptime(t, '%Y-%m-%dT%H:%M:%S.%f')
I think it is in YYYY-MM-DD with time as HH:MM:SS.sss , but am not able to figure out what -0500 could be...could it be subtracting -5 hrs for UTC?
Any help would be greatly appreciated
%z is what you need it's the timezone offset from UTC, see the docs
%z - UTC offset in the form +HHMM or -HHMM (empty string if the the object
is naive). (empty), +0000, -0400, +1030
In [89]:
t= "2017-01-05T14:23:33.986-0500"
dt.datetime.strptime(t, '%Y-%m-%dT%H:%M:%S.%f%z')
Out[89]:
datetime.datetime(2017, 1, 5, 14, 23, 33, 986000, tzinfo=datetime.timezone(datetime.timedelta(-1, 68400)))
EdChum's answer is definitely correct. However, there is an easier way to go about parsing dates - python-dateutil:
>>> from dateutil.parser import parse
>>> parse("2017-01-05T14:23:33.986-0500")
datetime.datetime(2017, 1, 5, 14, 23, 33, 986000, tzinfo=tzoffset(None, -18000))
The parse() function is very robust and able to handle a wide variety of date formats:
>>> parse("Friday January 6, 2017 11:12 AM")
datetime.datetime(2017, 1, 6, 11, 12)
This is on 3.6.0 with dateutil 2.6.0.
I have a unix timestamp in seconds (such as 1294778181) that I can convert to UTC using
from datetime import datetime
datetime.utcfromtimestamp(unix_timestamp)
Problem is, I would like to get the corresponding time in 'US/Eastern' (considering any DST) and I cannot use pytz and other utilities.
Only datetime is available to me.
Is that possible?
Thanks!
Easiest, but not supersmart solution is using timedelta
import datetime
>>> now = datetime.datetime.utcnow()
US/Eastern is 5 hours behind UTC, so let's just create thouse five hours as a timedelta object and make it negative, so that when reading back our code we can see that the offset is -5 and that there's no magic to deciding when to add and when to subtract timezone offset
>>> eastern_offset = -(datetime.timedelta(hours=5))
>>> eastern = now + eastern_offset
>>> now
datetime.datetime(2016, 8, 26, 20, 7, 12, 375841)
>>> eastern
datetime.datetime(2016, 8, 26, 15, 7, 12, 375841)
If we wanted to fix DST, we'd run the datetime through smoething like this (not entirely accurate, timezones are not my expertise (googling a bit now it changes each year, yuck))
if now.month > 2 and now.month < 12:
if (now.month == 3 and now.day > 12) or (now.month == 11 and now.day < 5):
eastern.offset(datetime.timedelta(hours=5))
You could go even into more detail, add hours, find out how exactly it changes each year... I'm not going to go through all that :)