Generating recurring dates using python? - python

How can I generate recurring dates using Python? For example I want to generate recurring date for "Third Friday of every second month". I want to generate recurring dates for daily, weekly, monthly, yearly (i.e., same as the recurrence function in Outlook Express).

import dateutil.rrule as dr
import dateutil.parser as dp
import dateutil.relativedelta as drel
start=dp.parse("19/02/2010") # Third Friday in Feb 2010
This generates the third Friday of every month
rr = dr.rrule(dr.MONTHLY,byweekday=drel.FR(3),dtstart=start, count=10)
This prints every third Friday:
print map(str,rr)
# ['2010-02-19 00:00:00', '2010-03-19 00:00:00', '2010-04-16 00:00:00', '2010-05-21 00:00:00', '2010-06-18 00:00:00', '2010-07-16 00:00:00', '2010-08-20 00:00:00', '2010-09-17 00:00:00', '2010-10-15 00:00:00', '2010-11-19 00:00:00']
rr is an iterable, so you can use slicing notation to pick out every other item. This prints the third Friday of every other month:
print map(str,rr[::2])
# ['2010-02-19 00:00:00', '2010-04-16 00:00:00', '2010-06-18 00:00:00', '2010-08-20 00:00:00', '2010-10-15 00:00:00']
Above, I used str to prettify the output a little bit. For more flexible string formatting of dates, use strftime: See http://au2.php.net/strftime or the man page for strftime for all the options.
print [d.strftime('%d/%m/%Y') for d in rr[::2]]
# ['19/02/2010', '16/04/2010', '18/06/2010', '20/08/2010', '15/10/2010']

You can give dateutil a try - especially its relativedelta and rrule fetures.

you may try to write this yourself. you will first need an iterator which generates dates separated by a given interval:
import datetime
def dateiter(start, resolution):
date = start
while True:
yield date
date += resolution
now, you can generate dates and filter them:
# generate a list of every tuesday of february
# this iterates over every day from now, and filtered according to the rules
# warning: infinite generator below, there is nothing to end the iteration
tuesdays_of_february = (date for date in dateiter(datetime.datetime.now(), datetime.timedelta(days=1)) if date.weekday() == 4 and date.month == 2)
you can call the iterator yourself until you have enough dates:
>>> next(tuesdays_of_february)
datetime.datetime(2010, 2, 19, 14, 25, 46, 171000)
now, you need to limit the results:
>>> from itertools import *
>>>
>>> # get the five next valid dates:
>>> list(islice(tuesdays_of_february),5)
[datetime.datetime(2010, 2,26, 14, 25, 46, 171000), datetime.datetime(2011, 2, 4
, 14, 25, 46, 171000), datetime.datetime(2011, 2, 11, 14, 25, 46, 171000), datet
ime.datetime(2011, 2, 18, 1 4, 25, 46, 171000), datetime.datetime(2011, 2, 25
, 14, 25, 46, 171000)]
>>>
>>> # or until a condition is met:
>>> list(takewhile( lambda date: date.year < 2014, tuesdays_of_february ))
[datetime.datetime(2012, 2, 3, 14, 25, 46, 171000), datetime.datetime(2012, 2, 1
0, 14, 25, 46, 171000), datetime.datetime(2012, 2, 17, 14, 25, 46, 171000), date
time.datetime(2012, 2, 24, 14, 25, 46, 171000), datetime.datetime(2013, 2, 1, 14
, 25, 46, 171000), datetime.datetime(2013, 2, 8, 14, 25, 46, 171000), datetime.d
atetime(2013, 2, 15, 14, 25, 46, 171000), datetime.datetime(2013, 2, 22, 14, 25,
46, 171000)]
don't forget to have a look at the documentation for the datetime module.

Related

Generate list of random datetimes in ISO8601 format in Python

I want to generate a list of length n with random datetime strings in Python within a range.
import datetime
start = datetime.datetime(2019,1,1,0,0,0).astimezone().replace(microsecond=0).isoformat()
end = datetime.datetime(2019,12,31,23,59,59).astimezone().replace(microsecond=0).isoformat()
I had asked a similar question before, but I did not use the correct format for datetime.What is the best way to achieve this?
Modifying the answer here for your format: https://stackoverflow.com/a/553448/7942856
from random import randrange
from datetime import timedelta, datetime
start = datetime(2019,1,1,0,0,0).astimezone().replace(microsecond=0)
end = datetime(2019,12,31,23,59,59).astimezone().replace(microsecond=0)
n = 5
def random_date(start, end):
"""
This function will return a random datetime between two datetime
objects.
"""
delta = end - start
int_delta = (delta.days * 24 * 60 * 60) + delta.seconds
random_second = randrange(int_delta)
return start + timedelta(seconds=random_second)
random_dates = [random_date(start, end) for i in range(n)]
Outputs:
[datetime.datetime(2019, 8, 6, 2, 25, 32, tzinfo=datetime.timezone(datetime.timedelta(seconds=39600), 'AUS Eastern Summer Time')), datetime.datetime(2019, 8, 5, 13, 2, 15, tzinfo=datetime.timezone(datetime.timedelta(seconds=39600), 'AUS Eastern Summer Time')), datetime.datetime(2019, 6, 24, 15, 57, 19, tzinfo=datetime.timezone(datetime.timedelta(seconds=39600), 'AUS Eastern Summer Time')), datetime.datetime(2019, 5, 3, 9, 35, 8, tzinfo=datetime.timezone(datetime.timedelta(seconds=39600), 'AUS Eastern Summer Time')), datetime.datetime(2019, 2, 12, 14, 33, 35, tzinfo=datetime.timezone(datetime.timedelta(seconds=39600), 'AUS Eastern Summer Time'))]
Then if you want the text ISO format, simply call .isoformat() on your list elements.
[random_date(start, end).isoformat() for i in range(n)]
#['2019-05-03T22:06:56+11:00', '2019-12-31T06:56:09+11:00', '2019-03-09T05:07:59+11:00', '2019-03-24T09:24:42+11:00', '2019-01-08T03:23:31+11:00']

Convert the date time stamp to local epoch datatime

Assume this is my date time stamp list:
[datetime.datetime(2017, 11, 17, 9, 33, 11), datetime.datetime(2017, 11, 17, 9, 33, 36), datetime.datetime(2017, 11, 17, 9, 33, 48)]
A lot of examples have been given for converting these values to epoch, but the values are in GMT.
How do we convert it to Epoch Local time?
To put it in simpler words. The general epoch conversion coverts the given date into epoch considering that the datetime given is in GMT. But the given date time is localtime!
>>> x = datetime.datetime(2017, 11, 17, 9, 33, 36)
>>> x.timestamp()
1510882416.0
>>> x.ctime()
'Fri Nov 17 09:33:36 2017'
You can use this:
l = [datetime.datetime(2017, 11, 17, 9, 33, 11), datetime.datetime(2017, 11, 17, 9, 33, 36), datetime.datetime(2017, 11, 17, 9, 33, 48)]
epo = [x.strftime('%s') for x in l]
print(epo)
# ['1510898591', '1510898616', '1510898628']
You can try arrow lib:
import arrow
import datetime
x = datetime.datetime(2017, 11, 17, 9, 33, 36)
time = arrow.get(x, 'local').shift(hours=-6) // here you can change hours to what you want
print time
>>2017-11-17T03:33:36+00:00
time = time.format('YYYY-MM-DD HH:mm:ss')
print time
>>2017-11-17 03:33:36

Why does relativedelta with positive arguments return a date in the past?

I have some trouble to understand the behavior of dateutil.relativedelta.
I understand that relativedelta could return past dates if I use negative arguments as specified in relativedelta doc.
However, when I provide positive parameters, I expect that it always return a date in the future... that seems legit right?
My use case is the following : we are Tuesday, it is 8:35. I want to get the date of the closest Monday and Tuesday at 6:00.
Here what I did. The first result seems correct to me, while the second one is wrong.
>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2016, 11, 29, 8, 35, 23, 786349)
>>> from dateutil import relativedelta
>>> now.weekday()
1
>>> now + relativedelta.relativedelta(weekday=0, hour=6, minute=0) # should give a time in the future
datetime.datetime(2016, 12, 5, 6, 0, 23, 786349) # here this is correct, in the future
>>> now + relativedelta.relativedelta(weekday=1, hour=6, minute=0) # should give a time in the future
datetime.datetime(2016, 11, 29, 6, 0, 23, 786349) # but this is in the past / I would expect result (2016, 12, 6, 6, 0, 23, 786349)
So , am I doing something wrong here ?
So according to your initial date, you're actually at 8AM, but you're targeting 6AM by using the hour param, if you're trying to increment one hour, you should use hours and minutes respectively
>>> now
datetime.datetime(2016, 11, 29, 3, 5, 41, 763818)
>>> now.weekday()
1
>>> now + relativedelta.relativedelta(weekday=1, hour=1)
datetime.datetime(2016, 11, 29, 1, 5, 41, 763818) # Notice how it's in the past
>>> now + relativedelta.relativedelta(weekday=1, hours=1)
datetime.datetime(2016, 11, 29, 4, 5, 41, 763818) # Notice how it's one hour in the future
>>> n + relativedelta.relativedelta(weekday=1, hour=6, minute=0, weeks=1)
datetime.datetime(2016, 12, 6, 6, 0, 41, 763818)
I think it's in the doc:
Starting with, about weekday:
These instances may receive a parameter N, specifying the Nth weekday, which could be positive or negative (like MO(+1) or MO(-2). Not specifying it is the same as specifying +1.
So by passing 1, it's like you're passing (1, 1)
Then, continuing on the doc, on the 7th dot of behavior of operations with relativedelta:
Notice that if the calculated date is already Monday, for example, using (0, 1) or (0, -1) won’t change the day.
So the 29th of November is already a Tuesday, and you're asking for a Tuesday.
So nothing changes.

Convert datetime to UTC

I have a date string like - 2015-01-05T10:30:47-0800,
It looks to me that this is some timezone because of the offset. How can I get a date string which is in the UTC timezone from the above date string.
I tried the following -
datestring = '2015-01-05T10:30:47-0800'
from dateutil import parser
d = parser.parse(datestring) # datetime.datetime(2015, 1, 5, 10, 30, 47, tzinfo=tzoffset(None, -28800))
import pytz
d.astimezone(pytz.timezone('UTC')) # datetime.datetime(2015, 1, 5, 18, 30, 47, tzinfo=<UTC>)
EDIT -
The above code returns the correct answer. My bad!
Try this:
>>> import dateutil.parser
>>> d = dateutil.parser.parse('2015-01-05T10:30:47-0800')
>>> d.astimezone(dateutil.tz.tzutc())
datetime.datetime(2015, 1, 5, 18, 30, 47, tzinfo=tzutc())

Making a calculation based on the time module with Python

I am trying to output an altered time based on the "time" module in Py. For instance. I gather raw_input for the script from a user and based on that input I want to get system time and subtract a number of days from it and use that time for another step.
Thanks,
There are examples of all these steps here.
The datetime module is likely what you want.
Here is an example:
>>> from datetime import datetime, timedelta
>>> s = raw_input('Input year month day hour minute second: ')
Input year month day hour minute second: 2011 10 31 14 30 00
'2011 10 31 14 30 00'
>>> fields = map(int, s.split())
>>> fields
[2011, 10, 31, 14, 30, 0]
>>> userdate = datetime(*[2011, 10, 31, 14, 30, 0])
>>> userdate
datetime.datetime(2011, 10, 31, 14, 30)
>>> userdate - timedelta(days=20)
datetime.datetime(2011, 10, 11, 14, 30)
>>> now = datetime.now()
>>> now
datetime.datetime(2011, 10, 31, 11, 38, 34, 856511)
>>> now + timedelta(hours=2)
datetime.datetime(2011, 10, 31, 13, 38, 34, 856511)

Categories

Resources