def get_from_date(self, date, interval): """ help function to make the creation monthly, yearly reports more generic. This function returns e.g. month or year from a given date """ if interval == 'yearly': return Bank_Date(date.year, 1, 1) if interval == 'monthly': return Bank_Date(date.year, date.month, 1) if interval == 'daily': return date raise TypeError("interval has to be either monthly or yearly")
def valid_date(date): """ routine for making a date out of anything that the user might have given to the function """ if date is None: return Bank_Date.today() if isinstance(date, Bank_Date): return date if isinstance(date, datetime): return Bank_Date.fromtimestamp(date.timestamp()) if isinstance(date, str): return parse_datestring(date) raise TypeError("Date must be at least from type datetime or callable")
def plot_stack_generic(X, Y, c, semantic, *reports, color_theme=C_cold_colors, color_offset=0): """ generic function for plotting stacks """ # bring the data together dates, data = join_data(X, Y) # format the dates to a readable format str_dates = [ Bank_Date.fromtimestamp(d).strftime(C_format_date) for d in dates ] add_labels(semantic, *reports, color_theme=color_theme, color_offset=color_offset) if len(data) > 0: stackplot(dates, data, colors=c) else: # if data is empty, plot at least zeros to make this plot more complete plot(dates, np.zeros(len(dates))) xticks(dates, str_dates, rotation=45)
def add_unique(self, from_acc, to_acc, payment, date, name = '', fixed = True, meta={}): """ adds a one-time payment to the list, optional give it a name """ if not isinstance(date, datetime): raise TypeError("Date must be at least from type datetime") self.check_errors_payment(payment) # converts any input to a function that returns the right value conv_payment = conv_payment_func(payment) self._uniques.append( Payment( from_acc = from_acc, to_acc = to_acc, date = Bank_Date.fromtimestamp(date.timestamp()), name = name, kind = 'unique', payment = conv_payment, fixed = fixed, meta = meta ) ) # sort the whole list with date as key self._uniques = sorted(self._uniques, key = lambda p: p['date'] )
def iter_regular_month(regular, date_start=None): """ creates an iterator for a regular payment. this function is for example used by payment to create iterators for every item in _regular regular: item of the structure Payments._regular date_start: date the payment generator wants to start the payments, this can be a date after regular['date_start'] """ if not date_start: date_start = regular['date_start'] else: # determine the greater date date_start = max(date_start, regular['date_start']) # if day is bigger than start_date.day, than this month is gonna # be the first payment if date_start.day <= regular['day']: i = 0 # otherwise it will be in the next month else: i = 1 date_start = Bank_Date(year=date_start.year, month=date_start.month, day=min( regular['day'], monthrange(date_start.year, date_start.month)[1]), hour=date_start.hour, minute=date_start.minute, second=date_start.second) date_stop = regular.get('date_stop', Bank_Date.max) stop_criteria = create_stop_criteria(date_stop) current_date = date_start.add_month(i) while stop_criteria(current_date): yield Payment(from_acc=regular['from_acc'], to_acc=regular['to_acc'], date=current_date, name=regular['name'], kind='regular', payment=regular['payment'], fixed=regular['fixed'], meta=regular['meta']) i += 1 current_date = date_start.add_month(i)
def parse_datestring(datestr): """ Tries to parse the datestring against a few common formats """ for format in date_formats: try: date = Bank_Date.strptime(datestr, format) return date except ValueError: pass
def append(self, status = None, date = None, **kwargs): """ adds either an instance of status to the list or data given to the append method as keyword arguments """ assert((status and not date) or (date and not status)) if date: status = Status( Bank_Date.fromtimestamp(date.timestamp()), **kwargs ) if not isinstance(status, Status): raise TypeError("status must be of type Status") self._statuses.append(status) # add potential new keys to the list self._keys = list(set(self._keys) | set(status.keys()))
def setUp(self): self.regular = { 'from_acc': 'Dummy', 'to_acc': 'Dummy', 'interval': 'month', 'day': 15, 'date_start': Bank_Date(2015, 3, 15), 'date_stop': Bank_Date(2015, 6, 15), 'payment': 3000, 'name': 'Test', 'fixed': True, 'meta': {} } self.infinite = { 'from_acc': 'Dummy', 'to_acc': 'Dummy', 'interval': 'month', 'day': 15, 'date_start': Bank_Date(2015, 3, 15), 'date_stop': Bank_Date.max, 'payment': 3000, 'name': 'Test', 'fixed': True, 'meta': {} } self.lastcal = { 'from_acc': 'Dummy', 'to_acc': 'Dummy', 'interval': 'month', 'day': 31, 'date_start': Bank_Date(2015, 1, 31), 'date_stop': Bank_Date(2015, 6, 15), 'payment': 3000, 'name': 'Test', 'fixed': True, 'meta': {} }
def add_regular(self, from_acc, to_acc, payment, interval, date_start, day=1, name='', date_stop = None, fixed = False, meta={}): """ Adds a regular payment to the list, with a given payment: amount to pay interval: 'monthly': every month 'quarter': every quarter with date_start as start month 'quarter_year': every quarter of a year (mar, jun, sep, dec) 'yearly': every year day: day to start with date_start: start date of this payment name : optional name fixed: only everything or nothing must be transfered (true) or depending on the receiving account a smaller amount can be transfered (false) """ if not interval in C_interval.keys(): raise ValueError("interval must be one of '" + '\',\''.join(C_interval)) if day >= 29: warnings.warn(("note that in months which have less days than {} the " + "payment will be transferred earlier").format(day) ) self.check_errors_payment(payment) if not date_stop: date_stop = Bank_Date.max else: date_stop = validate.valid_stop_date(date_stop) # converts any payment to a function conv_payment = conv_payment_func(payment) self._regular.append({'from_acc': from_acc, 'to_acc': to_acc, 'interval': interval, 'day' : day, 'date_start': Bank_Date.fromtimestamp(date_start.timestamp()), 'date_stop': date_stop, 'payment': conv_payment, 'name' : name, 'fixed': fixed, 'meta': meta } )