def week_calendar(username, period): config = data.CalendarConfig( lang='en', title=f"{username}'s Tasks", dates=period, show_year=True, mode='working_hours', legend=False, ) events = [] user_tasks = file.user_row('tasks.csv', user_name=username) for task in user_tasks: daytime = task['due_time'].split(" ") day = daytime[0] start = datetime.strftime(datetime.strptime(daytime[1], '%H:%M:%S'), '%H:%M') end = datetime.strftime( datetime.strptime(daytime[1], '%H:%M:%S') + timedelta(hours=1), '%H:%M') events.append(Event(task['title'], day=day, start=start, end=end)) data.validate_config(config) data.validate_events(events, config) calendar = Calendar.build(config) calendar.add_events(events) calendar.save(f"{username}_tasks.png")
def _draw_event(self, event: Event): """ The events have already been split to the separate days. The event is for 1 day only. """ day_number = (event.get_start_date(self.config) - self.config.get_date_range()[0]).days x = self.__get_event_x(day_number) y = self.__get_event_y(event.start_time, event.end_time) p1 = (x[0] + style.line_day_width / 2, y[0]) p2 = (x[1] - style.line_day_width / 2, y[1]) draw_rounded_rectangle(self.event_draw, [p1, p2], style.event_radius, outline=event.style.event_border, fill=event.style.event_fill, width=style.event_border_width) if not self.config.legend and event.name is not None: text_size = style.event_name_font.getsize_multiline(event.name) title_pos = ((x[0] + x[1]) / 2 - text_size[0] / 2, (y[0] + y[1]) / 2 - text_size[1] / 2) self.event_draw.multiline_text(title_pos, event.name, align='center', font=style.event_name_font, fill=style.event_name_color)
def add_event(self, event: Event) -> None: """ Skip the empty events with a duration of fewer than 0 seconds. Splits events, if needed, to the separate days. The event in the result list has to be for 1 day only. Cut the event's time out of the visible time range. Validate events. """ if event.get_duration_seconds(self.config) < 1: logging.warning( f"Skipping event, the duration is too small: {event}") return end_date: date = event.get_end_date(self.config) start_date: date = event.get_start_date(self.config) if end_date < self.config.get_date_range()[0]: logging.warning( f"Skipping event, it ends before the visible range: {event}") return if start_date > self.config.get_date_range()[1]: logging.warning( f"Skipping event, it starts after the visible range: {event}") return if start_date == end_date or ((end_date - start_date).days == 1 and event.end_time == time(0, 0)): self.__do_add_event(event) else: logging.debug(f'Splitting the event: {event}') iter_from: date = max(start_date, self.config.get_date_range()[0]) iter_to: date = min(end_date, self.config.get_date_range()[1]) for single_date in time_utils.date_range(iter_from, iter_to): next_date: date = single_date + timedelta(days=1) if single_date == start_date: fr: datetime = datetime.combine(single_date, event.start_time) to: datetime = datetime.combine(next_date, time(0, 0)) elif single_date == end_date: fr: datetime = datetime.combine(single_date, time(0, 0)) to: datetime = datetime.combine(single_date, event.end_time) else: fr: datetime = datetime.combine(single_date, time(0, 0)) to: datetime = datetime.combine(next_date, time(0, 0)) self.__do_add_event( Event(name=event.name, style=event.style, start=fr, end=to))
def add_event(self, *events: Event, **kwargs) -> None: """ Adds the event(s) to the list to draw them later. :param events: the event objects :param kwargs: the input arguments for the Event constructor """ if events: for event in events: self.events.add_event(event) if kwargs: self.events.add_event(Event(**kwargs))
def validate_event(event: Event, config: CalendarConfig): start_date, end_date = config.get_date_range() start_time = time(hour=config.get_hours_range()[0]) end_hour = config.get_hours_range()[1] if not (start_date <= event.get_start_date(config) <= end_date): logging.warning("Event can't be shown, because it is not in configured date range: {} not in [{}, {}]".format( event.get_start_date(config).strftime('%Y-%m-%d'), start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d') )) if event.start_time < start_time: logging.warning("Event can't be shown, because its start is before time range: {} is before {}".format( event.start_time.strftime('%H:%M'), start_time.strftime('%H:%M') )) if end_hour < 24 and time(hour=end_hour) < event.end_time: logging.warning("Event can't be shown, because its end is after time range: {} is before {}".format( event.end_time.strftime('%H:%M'), time(hour=end_hour).strftime('%H:%M') ))
from calendar_view.core.event import Event, EventStyles config = CalendarConfig( lang='en', title='Yoga Class Schedule', dates='Mo - Su', hours='8 - 22', show_date=False, legend=True, ) data.validate_config(config) events = [ Event(day_of_week=0, start='11:00', end='12:30', name='Ashtanga, 90 mins, with Gina', style=EventStyles.GRAY), Event(day_of_week=1, start='18:00', end='19:15', name='HOT Core Yoga, 75 mins, with David', style=EventStyles.RED), Event(day_of_week=2, start='09:00', end='10:00', name='Meditation - Yoga Nidra, 60 mins, with Heena', style=EventStyles.BLUE), Event(day_of_week=2, start='19:00', end='20:15',
from calendar_view.calendar import Calendar from calendar_view.core import data from calendar_view.core.event import Event config = data.CalendarConfig( lang='en', title='Sprint 23', dates='2019-09-23 - 2019-09-27', show_year=True, mode='working_hours', legend=False, ) events = [ Event('Planning', day='2019-09-23', start='11:00', end='13:00'), Event('Demo', day='2019-09-27', start='15:00', end='16:00'), Event('Retrospective', day='2019-09-27', start='17:00', end='18:00'), ] data.validate_config(config) data.validate_events(events, config) calendar = Calendar.build(config) calendar.add_events(events) calendar.save("sprint_23.png")
def _get_event_legend_text(self, event: Event) -> str: date_text = self._get_day_title(event.get_start_date(self.config)) time_text = '{:%H:%M} - {:%H:%M}'.format(event.start_time, event.end_time) return '{}, {} - {}'.format(date_text, time_text, event.name)