Im trying to provide dynamic value to relativedelta function, i.e relativedelta(days=1) i would like to assign dynamic function value days, months, years to the function. Consider my situation as follows.
I will get list dynamicaly as follows:
Ex: 1
list = ['today', 'minus', '1', 'days']
Ex: 2
list = ['today', 'plus', '1', 'year']
Ex: 3
list = ['today', 'plus', '1', 'months']
I wrote my code to handle the calculation
import operator
from datetime import datetime
from datetime import date
from dateutil.relativedelta import relativedelta
operations = {
'plus': operator.add,
'minus': operator.sub,
}
today = date.today()
new_date = self.operations['plus'](today, relativedelta(days=1))
# the above is some thing like [today + relativedelta(days=1)]
What I'm trying to do is like operations I would like to assign days, months, years to the relativedelta() function, but I couldn't able to do it. Any suggested way to do it?
Found a way to do it!
We can use the **expression call syntax to pass in a dictionary to a function instead, it'll be expanded into keyword arguments (which your **kwargs function parameter will capture again):
attributes = {'days': 1}
relativedelta(**attributes)
Related
Consider the following Polars dataframe:
import polars as pl
df = pl.DataFrame({'year': [2023], 'month': [2], 'day': [1]})
I want to construct a date column from year, month and day. I know this can be done by first concatenating into a string and then parsing this:
df.with_column(
pl.concat_str([pl.col('year'), pl.col('month'), pl.col('day')], sep='-')
.str.strptime(pl.Date).alias('date')
)
But that seems like a detour. Is it possible to construct it directly with the three inputs? Something like this (that doesn't work):
import datetime
df.with_column(
datetime.date(pl.col('year'), pl.col('month'), pl.col('day')).alias('date')
)
polars has a pl.datetime and pl.date function that works the same as base datetime except that it takes expressions so you can just do
df.with_columns(pl.date(pl.col('year'), pl.col('month'), pl.col('day')).alias('date'))
I have to subtract 2 dates using datetime like this:
datetime.datetime.now() - datetime.timedelta(minutes=15)
# subtracting 15 minutes
The problem is that i don't necessarily need to subtract minutes.
I have a dictionary that tells what i should subtract.
period = {'quantity': '15', 'time': 'minutes'}
But i need that when the dictionary changes, the subtracted time also changes. Like this:
if period['time'] == 'minutes':
tempo_atras = datetime.datetime.now() -datetime.timedelta(minutes=int(period['quantity']))
elif period['time'] == 'hours':
tempo_atras = datetime.datetime.now() - datetime.timedelta(hours=int(period['quantity']))
elif period['time'] == 'days':
tempo_atras = datetime.datetime.now() - datetime.timedelta(days=int(period['quantity']))
elif period['time'] == 'weeks':
tempo_atras = datetime.datetime.now() - datetime.timedelta(weeks=int(period['quantity']))
I feel that the way i wrote it is not clean, so i need a way to convert the period['time'] string in the function parameter; something like:
tempo_atras = datetime.datetime.now() - datetime.timedelta(period['time']=int(period['quantity']))
How can i do this?
You can use the dictionary unpacking operator ** to expand a dict into keyword arguments, so you just need to make the dict first.
q = {period['time']: int(period['quantity'])}
tempo_atras = datetime.datetime.now() - datetime.timedelta(**q)
Docs:
Tutorial: Unpacking Argument Lists
Reference: Calls
You have to convert the dictionary so that the period is pointing to the quantity. Then use dictionary unpacking normally.
import datetime
period = {'quantity': '15', 'time': 'minutes'}
# convert the dictionary to a dictionary of "minutes"= "15"
period = {period['time']: int(period['quantity'])}
print(period)
tempo_atras = datetime.datetime.now() - datetime.timedelta(**period)
Note: you can read more about this format (and the * format for lists) here: More on Defining Functions
Given a time zone abbreviation, is there a way to get a list of possible time zones?
Like IST could mean one of the following:
Asia/Kolkata (India)
Asia/Tel_Aviv (Israel)
Europe/Dublin (Ireland)
What I was looking for was a way to get ['Asia/Kolkata', 'Asia/Tel_Aviv', 'Europe/Dublin'] as output when 'IST' is given as input.
I was hoping that there would a way using the standard modules itself. Can it be done with the new zoneinfo module?
Being inspired by this answer, I did
from datetime import datetime as dt
import zoneinfo
s = zoneinfo.available_timezones()
d = dict()
for tz in s:
t = z.ZoneInfo(tz).tzname(dt.utcnow())
if t not in d:
d[t] = [tz]
else:
d[t].append(tz)
But this is giving 'PDT' as
'PDT': ['America/Ensenada',
'America/Santa_Isabel',
'Mexico/BajaNorte',
'US/Pacific-New',
'US/Pacific',
'America/Vancouver',
'PST8PDT',
'America/Tijuana',
'America/Los_Angeles',
and 'PST' as just
'PST': ['Asia/Manila'],
But wouldn't 'America/Los_Angeles' also come under 'PST' at some point (not right now but later on).
I'm obviously missing something, but couldn't understand what it is..
Can there be a way to get the list of possible timezones from a time zone abbreviation?
extending the linked answer, in a kind-of-naive approach, you can generate your lookup table for a specific year like
from collections import defaultdict
from datetime import datetime, timedelta
import zoneinfo
year = 2021
checkdays = [datetime(year, 1, 1) + timedelta(i) for i in range(0, 365, 5)]
abbreviationmap = defaultdict(set)
for d in checkdays:
for z in zoneinfo.available_timezones():
abbreviationmap[zoneinfo.ZoneInfo(z).tzname(d)].add(z)
print(sorted(abbreviationmap['PDT']))
# ['America/Ensenada', 'America/Los_Angeles', 'America/Santa_Isabel',
# 'America/Tijuana', 'America/Vancouver', 'Canada/Pacific', 'Mexico/BajaNorte',
# 'PST8PDT', 'US/Pacific']
I have a dict looking like this:
visits = {'visit_1': {'date': '23-11-2016'},
'visit_2': {'date': '23-12-2016'}}
The dict consists of a lot of visits, where the 'date' is relative to the visit_1 date.
Question: Is it possible for a python dict to refer to self? Something like this:
from datetime import datetime, timedelta
visits = {'visit_1': {'date': datetime('23-11-2016')},
'visit_2': {'date': <reference_to_self>['visit_1']['date'] + timedelta(weeks=4)}
EDIT:
The first visit is not known at initialization. The dict defines a fairly complicated visit sequence (used in treatment of cancer patients)
If I understand the problem correctly, you can define the first visit date prior to creating the dictionary:
from datetime import datetime, timedelta
visit1_date = datetime(2016, 11, 23)
visits = {'visit_1': {'date': visit1_date},
'visit_2': {'date': visit1_date + timedelta(weeks=4)}}
print(visits)
To extend that a little bit further, you may have a visits factory that would dynamically create a dictionary of visits based on a start date and the number of visits (assuming the visits come every 4 weeks evenly):
from datetime import datetime, timedelta
def visit_factory(start_date, number_of_visits):
return {'visit_%d' % (index + 1): start_date + timedelta(weeks=4 * index)
for index in range(number_of_visits)}
visits = visit_factory(datetime(2016, 11, 23), 2)
print(visits)
Python containers (e.g. dictionaries) can definately refer to them selves. The problem with your example is that you are not just storing a reference, but the result of an expression (which involves the reference). This result will not itself keep any reference to how it was made, and so you loose the reference.
Another Small problem is that you cannot create an object and reference it in the same expression. Since dicts are mutable though, you can just create some of its elements first, and then add elements to it in further expression, referencing the dict via its variable name.
Is it possible to achieve something like this?
def subtract_from_date(date, time_unit, num):
return date - timedelta(time_unit=num)
Basically I am feeling too lazy to put if elif conditions for various input time units like minutes, hours, weeks, days etc.
You can use a dictionary and apply it as a mapping argument:
timedelta(**{time_unit: num})
Demo:
>>> from datetime import datetime, timedelta, date
>>> def subtract_from_date(date, time_unit, num):
... return date - timedelta(**{time_unit: num})
...
>>> subtract_from_date(date.today(), 'days', 5)
datetime.date(2015, 3, 21)