How to get rrule.between() to only include start timestamp - python

How would I create an rrule that excludes only the end timestamp using dateutil? Would I have to create a custom function or is there a way to do it natively?
here is an example
rule = rrule.rrule(rule.HOURLY,tsstart=somedate,until=somedate_four_hours_later)
I want the output to EXCLUDE somedate_four_hours_later and only generate 4 timestamps, somedate, somedate+1 hour, etc.

One way to do this is to use an rruleset, which allows you to combine recurrence rules and specific dates as required. In this case, what you'd do is set the until date as an exdate (excluded date):
from dateutil import rrule
from datetime import datetime, timedelta
dtstart = datetime(2015, 1, 3, 12)
dtuntil = datetime(2015, 1, 3, 16)
rr = rrule.rrule(freq=rrule.HOURLY, dtstart=dtstart, until=dtuntil)
# Add your rrule to the ruleset, then exclude the until date from the rule set
rrset = rrule.rruleset()
rrset.rrule(rr)
l1 = list(rrset)
rrset.exdate(dtuntil)
l2 = list(rrset)
print(l1[-1]) # 2015-01-03 16:00:00
print(l2[-1]) # 2015-01-03 15:00:00
The rrule itself will include the until date, but the exdate will exclude it from the rruleset.

You can set the count:
In [1]: from dateutil import rrule
In [2]: from datetime import datetime, timedelta
In [3]: st = datetime(2016, 7, 5, 23, 30)
In [4]: rule = rrule.rrule(rrule.HOURLY, st, count=4)
In [5]: print(list(rule))
[datetime.datetime(2016, 7, 5, 23, 30), datetime.datetime(2016, 7, 6, 0, 30), datetime.datetime(2016, 7, 6, 1, 30), datetime.datetime(2016, 7, 6, 2, 30)]
Or use timedelta adding three hours to the start:
from datetime import datetime, timedelta
st = datetime(2016, 7, 5, 23, 30)
rule = rrule.rrule(rrule.HOURLY, st, until=(st + timedelta(hours=3)))

Related

Why is only one date under DST influence?

I've been reading the pytz and datetime module documentation but I can't figure out why one date is under DST and the other is not.
import pytz
import datetime
mytz = pytz.timezone('America/New_York')
od = datetime.datetime(2021, 7, 1, 4, 0)
mytz.localize(od)
# Out: datetime.datetime(2021, 7, 1, 4, 0, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
mytz.localize(od).dst()
# Out: datetime.timedelta(0, 3600)
dt = datetime.datetime(2089, 7, 1, 4, 0)
mytz.localize(dt)
# Out: datetime.datetime(2089, 7, 1, 4, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
mytz.localize(dt).dst()
# Out: datetime.timedelta(0)
If you look at the source of the time zone rules, you find that they can have a keyword "max" specified that "is used to extend a rule’s application into the indefinite future" ref. For the US, you can find that here. Unless otherwise specified, DST just continues to be applied during the specified period of the year. But keep in mind that this does not mean that it will actually be the case in the future, since time zones are subject to political decisions.
As an addition to #balmy 's comment suggesting this is a deficiency of pytz, Python 3.9's zoneinfo gives the result to be expected from the above:
import datetime
from zoneinfo import ZoneInfo
od = datetime.datetime(2021, 7, 1, 4, 0, tzinfo=ZoneInfo('America/New_York'))
print(od.dst())
# 1:00:00
dt = datetime.datetime(2089, 7, 1, 4, 0, tzinfo=ZoneInfo('America/New_York'))
print(dt.dst())
# 1:00:00

Parse a list of numbers in datetime in Python Pandas

I have a dataframe of transportation data.
The datetime fields are logged in this format: [2020, 12, 10, 15, 0, 5, 18000000].
How do I parse these as datetime objects?
You can pass it with * to the datetime.datetime constructor and use any pandas function to apply this to every value in your pandas.Series.
>>> from datetime import datetime
>>> datetime(*[2020, 12, 10, 15, 0, 5, 18000])
datetime.datetime(2020, 12, 10, 15, 0, 5, 18000)
One additional moment: you will need to update microsecond field.
E.g.
from datetime import datetime
import pandas as pd
df = pd.DataFrame({"example": [[2020, 12, 10, 15, 0, 5, 18000000]]})
df.example = df.example.apply(lambda x: datetime(
*(v if i != len(x) - 1 else v // 1000 for i, v in enumerate(x))
))

Python subtract dates or days from date to get years, months, days

I am trying to subtract two dates or days from today's date. I want to get the result in years, months, days. How to do that?
Expecting 1 year, 2 months, 5 days, 20 days, 3 months, 2 days ago, etc. instead of just days.
import datetime
import pytz
tz='US/Pacific'
birthday = datetime.datetime(2020, 2, 19, 12, 0, 0)
>>> import datetime
>>> import pytz
>>> tz='US/Pacific'
>>> birthday = datetime.datetime(2020, 2, 19, 12, 0, 0)
>>> diff = datetime.datetime.now() - birthday
>>>
>>> diff
datetime.timedelta(days=326, seconds=39130, microseconds=319509)
>>>
>>> birthday = datetime.datetime(2015, 2, 19, 12, 0, 0)
>>> diff = datetime.datetime.now() - birthday
>>> diff
datetime.timedelta(days=2152, seconds=39151, microseconds=823846)
>>>
>>> diff.days
2152
Use dateutil.relativedelta from the dateutil package:
import datetime
from dateutil.relativedelta import relativedelta
>>> relativedelta(datetime.datetime.now(), datetime.datetime(2020, 2, 19, 12, 0, 0))
relativedelta(months=+10, days=+23, hours=+4, minutes=+8, seconds=+42, microseconds=+204978)
>>> relativedelta(datetime.datetime.now(), datetime.datetime(2015, 2, 19, 12, 0, 0))
relativedelta(years=+5, months=+10, days=+23, hours=+4, minutes=+9, seconds=+10, microseconds=+624971)
You can extract years, months, etc. like relativedelta().years, relativedelta().months, etc.
This answer may be helped you. But also you can check this using timetuple()
from datetime import datetime
import datetime
import pytz
tz = 'US/Pacific'
birthday = datetime.datetime(2020, 2, 19, 12, 0, 0)
b = birthday.timetuple()
n = datetime.datetime.now().timetuple()
print(f'Year diff: {n.tm_year-b.tm_year}')
print(f'Month diff: {n.tm_mon-b.tm_mon}')
print(f'Day diff: {n.tm_mday-b.tm_mday}')

Convert two datetime objects to monthly datetime range

I have two datetime objects, let's say start_date and end_date. What I want to do is to make a list of datetime objects.
>>> from datetime import datetime
>>> from dateutil.rrule import rrule, MONTHLY
>>> start_date = datetime(2018, 9, 6, 0,)
>>> end_date = datetime(2018, 11, 26, 23, 59, 59)
>>> list(rrule(MONTHLY, dtstart=start_date, until=end_date))
[datetime.datetime(2018, 9, 6, 0, 0), datetime.datetime(2018, 10, 6, 0, 0), datetime.datetime(2018, 11, 6, 0, 0)]
I can do this with rrule(), it's moving from date to date but I want it to go month-wise and also include the end_date,
[
datetime.datetime(2018,9,6,0,0),
datetime.datetime(2018,9,30,23,59),
datetime.datetime(2018,10,1,0,0),
datetime.datetime(2018,10,31,23,59),
datetime.datetime(2018,11,1,0,0),
datetime.datetime(2018,11,26,23,59)
]
I would prefer to do this without using pandas or numpy.
Try this
import datetime
def last_day_of_month(date):
if date.month == 12:
return date.replace(day=31)
return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)
def desired_output(start_date,end_date):
curr_date = start_date
desired_list = []
desired_list.append(start_date)
while curr_date<=end_date:
if last_day_of_month(curr_date)>end_date:
desired_list.append(end_date)
break
desired_list.append(last_day_of_month(curr_date))
curr_date = last_day_of_month(curr_date) + datetime.timedelta(1)
if curr_date<end_date:
desired_list.append(curr_date)
else:
break
return desired_list
print(desired_output(datetime.datetime(2018,9,6,0,0), datetime.datetime(2018,12,26,0,0)))
here's how you can get a list of dates between two ranges. you can modify it to add certain dates.
from datetime import datetime
from datetime import timedelta
import calendar
dates = []
start_date = datetime(2018, 9, 6, 0,)
end_date = datetime(2018, 10, 10, 0,)
index_date = start_date
while True:
index_date = index_date
dates.append(index_date)
dayy = calendar.monthrange(index_date.year,index_date.month)
index_date = index_date.replace(day= dayy[1])
if index_date > end_date:
break
dates.append(index_date)
index_date = index_date + timedelta(days=1)
if index_date > end_date:
break
print dates

Datetime - 10 Hours

Consider:
now = datetime.datetime.now()
now
datetime.datetime(2009, 11, 6, 16, 6, 42, 812098)
How would I create a new datetime object (past) and minus n values from the hours?
Use timedelta in the datetime module:
import datetime
now = datetime.datetime.now()
past = now - datetime.timedelta(hours=10)
Use a timedelta object.
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2009, 11, 6, 16, 35, 50, 593000)
>>> ten_hours = datetime.timedelta(hours=10)
>>> now + ten_hours
datetime.datetime(2009, 11, 7, 2, 35, 50, 593000)
>>> now - ten_hours
datetime.datetime(2009, 11, 6, 6, 35, 50, 593000)
Use a timedelta object.
from datetime import datetime
back = datetime.now() - timedelta(hours=10)

Categories

Resources