def hours_inside(self, start_time: datetime, end_time: datetime) -> float: exact_start_weekday = start_time.isoweekday() + self.to_exact_num_days(start_time.time()) exact_end_weekday = end_time.isoweekday() + self.to_exact_num_days(end_time.time()) return self.hours_overlap( (self.exact_start_weekday, self.exact_end_weekday), (exact_start_weekday, exact_end_weekday) )
def calc_diff_available(resource: str, t1: datetime, t2: datetime) -> int: """return -1 for error, assume t2>t1 ordered""" rc_routines = rc_weekly.get(resource) if not rc_routines: print("no weektable") return -1 tstamp = [t1, t2] wday = [t.isoweekday() for t in tstamp] # print(wday) timetable = [rc_routines.get(w) for w in wday] mod = [t.hour * 60 + t.minute for t in tstamp] mhcoord = [timetable[0].to_mh(mod[0]), timetable[1].to_mh(mod[1])] while not mhcoord[0].to_available_next(): t1 = datetime.combine(t1.date(), datetime.min.time()) + timedelta(days=1) tbl = rc_routines.get(t1.isoweekday()) mhcoord[0] = tbl.to_mh(0) if t2 < t1: print(f"rc={resource}, start={str(t1)}, end={str(t2)}") print("wrong order") return -1 while not mhcoord[1].to_available_prev(): # 今天前面沒時間 if t2.time() != datetime.min.time(): t2 = datetime.combine(t2.date(), datetime.min.time()) # 今天開始 t2 += timedelta(minutes=-1) # 昨天 23:59 else: t2 += timedelta(days=-1) # 往前一天 tbl = rc_routines.get(t2.isoweekday()) mhcoord[1] = tbl.to_mh(t2.hour * 60 + t2.minute) tstamp = [t1, t2] wday = [t.isoweekday() for t in tstamp] mod = [t.hour * 60 + t.minute for t in tstamp] restinday = [mh.get_leftover() for mh in mhcoord] minofday = [mh.get_mhcoord() for mh in mhcoord] if any(mh == -1 for mh in minofday): return -1 if t1.date() == t2.date(): return (minofday[1] - minofday[0]) partition = [0] * 3 # calc firstday left over # print(timetable[0].iloc[-1]) partition[0] = restinday[0] # calc lastday works partition[2] = minofday[1] # calc midday cnt_mid_day = (t2.date() - t1.date()).days - 1 # print(cnt_mid_day) wt = get_worktime(resource) partition[1] = calc_midday_worktime(wt, wday[0], cnt_mid_day) # print(partition) return sum(partition)
def _set_due_date_when_is_weekend_day(due_date: datetime, num_of_days_to_saturday: int, num_of_days_to_sunday: int) -> datetime: """ Set due date when it's saturday by num_of_days_to_saturday or sunday by num_of_days_to_sunday """ if due_date.isoweekday() == 6: due_date += timedelta(days=num_of_days_to_saturday) elif due_date.isoweekday() == 7: due_date += timedelta(days=num_of_days_to_sunday) return due_date
def add_time( subgroup: Subgroup, desired_datetime: datetime.datetime, use_week_ends_days: bool = True, use_week_sat_sun: bool = False, use_7days: bool = False, use_quarters: bool = False, ) -> Subgroup: """Add a time component to the subgroup depending on the parameters. Added in v_0.2. Args: use_week_ends_days: Distinguish the subgroups between weekdays and weekends. Defaults to True. use_week_sat_sun: Distinguish the subgroups between weekdays, saturday and sunday. Defaults to False. use_7days: Distinguish the subgroup between the 7 days of the weeks. Defaults to False. use_quarters: Distinguish the subgroup depending on the quarters of a year. Defaults to False. """ if sum((use_7days, use_week_ends_days, use_week_sat_sun)) > 1: raise ValueError( "Can use only one of 'use_7days', 'use_week_ends_days'," " 'use_week_sat_sun' " ) elif use_week_ends_days: if desired_datetime.isoweekday() <= 5: subgroup["weekday"] = [1, 2, 3, 4, 5] else: subgroup["weekday"] = [6, 7] elif use_week_sat_sun: if desired_datetime.isoweekday() <= 5: subgroup["weekday"] = [1, 2, 3, 4, 5] else: subgroup["weekday"] = desired_datetime.isoweekday() elif use_7days: subgroup["weekday"] = desired_datetime.isoweekday() else: # No type of day was specifiy subgroup.pop("weekday", None) # update the quarter if required if use_quarters: subgroup["quarter"] = (desired_datetime.month - 1) // 3 + 1 else: # Makes sure quarter is not in here subgroup.pop("quarter", None) return subgroup
def find_matching_timeslot(start_time: datetime, duration: timedelta, subject: Subject, requester, qs: QuerySet['TimeSlot']) -> Optional['TimeSlot']: qs = qs.prefetch_related("appointment_set").select_related('owner').filter( start_time__lte=start_time, start_time__time__lte=start_time.timetz(), start_time__iso_week_day=start_time.isoweekday(), duration__gte=duration, owner__tutordata__subjects=subject, owner__tutordata__verified=True) if settings.NAKLAR_SCHEDULING_SCHOOLDATA: qs = qs.filter( owner__tutordata__schooldata=requester.studentdata.school_data) qs = qs.annotate(num_appointments=Count( 'owner__timeslot__appointment', filter=Q(owner__timeslot__appointment__start_time__gte=Now())) ).order_by('num_appointments') for timeslot in qs: for available in timeslot.available_slots( earliest_start=timezone.now() + timedelta( minutes=settings.NAKLAR_SCHEDULING_APPOINTMENT_DISTANCE)): if (start_time >= available.start_time and available.start_time + available.duration >= start_time + duration): return available.parent return None
def next_run(self, current_time: datetime.datetime) -> datetime.datetime: """Given the current time, when is the next scheduled run?""" # if next run is next day, get smallest hour, smallest minute # if next run is today, future hour, get smallest minute # if next run is today, this hour, get next greatest minute next_run = datetime.datetime(current_time.year, current_time.month, current_time.day, tzinfo=current_time.tzinfo) weekday = current_time.isoweekday() weekday = 0 if weekday == 7 else weekday # Move Sunday to day 0 if weekday in self.weekdays: # could be a run today if current_time.hour in self.hours: # could be a run this hour for minute in self.minutes: if minute > current_time.minute: # there is a run this hour return next_run.replace(hour=current_time.hour, minute=minute) # no run this hour, check future hours for hour in self.hours: if hour > current_time.hour: # there is a run today return next_run.replace(hour=hour, minute=self.minutes[0]) # no run today, look for next matching weekday for day in range(1, 7): next_run += datetime.timedelta(days=1) weekday = next_run.isoweekday() weekday = 0 if weekday == 7 else weekday # Move Sunday to day 0 if weekday in self.weekdays: return next_run.replace(hour=self.hours[0], minute=self.minutes[0]) raise RuntimeError('No next run found for schedule {}'.format( self.schedule))
def get_data_points_for_day(shift_date: datetime): """ Create input datapoints for ML model """ # Retrieve common features among all data points month = shift_date.month year = shift_date.year day_of_week = shift_date.isoweekday() week_of_month = get_week_of_month(shift_date) datapoints = [] # Initialize minimum and maximum shift time for the day start_time = datetime(year, month, shift_date.day, SHIFT_START_TIME) end_time = datetime(year, month, shift_date.day, SHIFT_END_TIME) # Retrieve all possible shift intervals for the day split_shift_time = get_split_shift_time(start_time, end_time) # Add datapoint for each interval for interval in split_shift_time: start = interval[0].strftime('%H%M') end = interval[1].strftime('%H%M') datapoints.append({ "month": month, "year": year, "day_of_week": day_of_week, "week_of_month": week_of_month, "start_time": start, "end_time": end, }) return datapoints
def cronable(pattern: str, moment: datetime = None) -> bool: """Check if a datetime moment matches the given cron pattern. .--------------- minute (0-59) | .------------ hour (0-23) | | .--------- month_day (1-31) | | | .------ month (1-12) | | | | .--- week_day (1-7; sunday=7) | | | | | * * * * * cron command pattern """ valid_characters = '0123456789 */!' if any(char not in valid_characters for char in pattern): raise ValueError( f'Invalid cron pattern. Use "{valid_characters}" only.') moment = moment or datetime.now(timezone.utc) second = '*' minute, hour, month_day, month, week_day = pattern.split() if '!' in minute: symbol, value = minute.split("!") second, minute = (f'*/{value}' if symbol else value, '*') return (_check_field(second, moment.second) and _check_field(minute, moment.minute) and _check_field(hour, moment.hour) and _check_field(month_day, moment.day) and _check_field(month, moment.month) and _check_field(week_day, moment.isoweekday()))
def changeDateMonth(date:datetime,change_month:int) -> datetime: temp_month = date.month + change_month # print("changeDateMonth:" + str(date.month) + " to " + str(temp_month)) if(temp_month >= 13): year = temp_month//12 month = temp_month%12 if(month == 0): month = 12 date = datetime(year = date.year + year,month = month,day = check_monthDate(month,date.day)) elif(temp_month <= 0): temp_month = abs(temp_month) year = temp_month//12 month = temp_month%12 year = - 1 - year if(month == 0): month = 12 else: month = 12 - month date = datetime(year = date.year + year,month = month,day = check_monthDate(month,date.day)) else: date = datetime(year = date.year,month = temp_month,day = check_monthDate(temp_month,date.day)) Temp_date = date while date.isoweekday() in [6,7]: if Temp_date.day < 15: date = backWorkDays(date,-1) else: date = backWorkDays(date,1) return date
def is_working_time( self, date_time: datetime.datetime ) -> bool: # FIXME: There should be extra logic to check if start and end time fall to # FIXME: different dates. But I guess it should be an extremely rare case for now. date_time = self.with_salon_tz(date_time) if self.special_available_dates.filter( date=date_time.date(), is_available=False ).exists(): # stylist has specifically marked this date as unavailable return False try: available_weekday: StylistAvailableWeekDay = self.available_days.get( weekday=date_time.isoweekday(), work_start_at__lte=date_time.time(), is_available=True ) last_slot_end_time = self.salon.timezone.localize( datetime.datetime.combine( datetime.date.today(), available_weekday.get_slot_end_time(), )).time() if (date_time + self.service_time_gap).time() <= last_slot_end_time: return True except StylistAvailableWeekDay.DoesNotExist: pass return False
def is_working_day(self, date_time: datetime.datetime): is_working_day: bool = self.available_days.filter( weekday=date_time.isoweekday(), is_available=True).exists() is_special_non_working_day = self.special_available_dates.filter( date=self.with_salon_tz(date_time).date(), is_available=False ).exists() return is_working_day and not is_special_non_working_day
def isOpen(date: datetime.datetime) -> bool: aux = date.isoweekday() if aux == 1 or aux < 6: dayVerif = models.Phydata.objects.filter(jours='1').get() else: dayVerif = models.Phydata.objects.filter(jours=str(aux)).get() return dayVerif.isOpen
def set_datetime(self, value: datetime.datetime): self.i2c.write_byte_data(self.address, self.REG["SECONDS"], self.int2bcd(value.second)) self.i2c.write_byte_data(self.address, self.REG["MINUTES"], self.int2bcd(value.minute)) self.i2c.write_byte_data(self.address, self.REG["HOUR"], self.int2bcd(value.hour)) self.i2c.write_byte_data(self.address, self.REG["DATE"], self.int2bcd(value.day)) self.i2c.write_byte_data(self.address, self.REG["MONTH"], self.int2bcd(value.month)) self.i2c.write_byte_data(self.address, self.REG["YEAR"], self.int2bcd(value.year)) self.i2c.write_byte_data(self.address, self.REG["DAY"], value.isoweekday())
def is_in_time(self, t: datetime) -> bool: """ Check whether provided time is inside the range of this silencing period. :return: True if the time is inside """ return self.start.to_tuple() <= (t.isoweekday(), t.hour, t.minute) \ <= self.stop.to_tuple()
def _validate_submit_date(submit_date: datetime) -> None: """ Check weekend day and hour range (5AM-7PM) of submit_date """ if submit_date.isoweekday() > 5: raise ValueError(INVALID_DAY_WEEKEND) if submit_date.hour > 17: raise ValueError(INVALID_BIGGER_HOUR) if submit_date.hour < 9: raise ValueError(INVALID_LESS_HOUR)
def minutes_left(self, moment: datetime.datetime) -> int: """Get the minutes left in the window week for a given moment. Returns: 0 if the moment falls outside of a window, or the number of minutes left until the window ends if the current moment is inside a window. """ day = self.from_iso_weekday(moment.isoweekday()) return day.minutes_left(moment.time())
def get_next_occurrence(recur: RecurrenceModel, start_date: datetime) -> Optional[datetime]: # start_date should be in the end users timezone for day of week to work correctly day_of_week_map = { "Sun": 7, "Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6 } try: if recur["Frequency"] == "Day": return start_date + timedelta(days=recur["FrequencyCount"]) if recur["Frequency"] == "Week": start_date = start_date + timedelta(weeks=recur["FrequencyCount"]) if recur["Day_of_week"] is not None and start_date.isoweekday( ) != day_of_week_map[recur["Day_of_week"]]: expected_weekday = day_of_week_map[recur["Day_of_week"]] % 7 actual_weekday = start_date.isoweekday() % 7 diff_in_days = expected_weekday - actual_weekday if diff_in_days < 0: diff_in_days = 7 + diff_in_days start_date = start_date + timedelta(days=diff_in_days) return start_date if recur["Frequency"] == "Month": to_month = start_date.month + recur["FrequencyCount"] to_year = start_date.year if to_month > 12: to_year = to_year + 1 to_month = to_month % 12 return start_date.replace(year=to_year, month=to_month) if recur["Frequency"] == "Year": to_year = start_date.year + recur["FrequencyCount"] try: start_date = start_date.replace(year=to_year) except ValueError: start_date = start_date + timedelta(days=-1) # Feb 29th start_date = start_date.replace(year=to_year) return start_date except: pass return None
def get_datetime_of_week_start(original: datetime) -> datetime: """ Given a date, returns the most recent sunday of that date, at the time 11:59pm Eg. If given the datetime "monday 21st of march, 2pm" it will return "Sunday 20th march, 11:59pm". """ days_ahead = original.isoweekday() original_ = original - timedelta(days=days_ahead) return original_.replace(hour=23, minute=59)
def __is_date_wednesday(date: dt) -> bool: """Checks if a given date is a wednesday Args: date (dt): Date Returns: bool: True if wednesday, False if not """ return (date.isoweekday() == 3)
def is_in_range_or_equals(self, dt: datetime): weekday = dt.isoweekday() if weekday == 7: weekday = 0 if self._invoke_conditions_compiled is True: return True return self._invoke_conditions_compiled(self._conditions, dt.minute, dt.hour, dt.day, dt.month, weekday)
def __init__(self, word: Word, user: User, date: datetime, score, search_count): self.word_id = word.id self.user_id = user.id self.year = date.year self.month = date.month self.day = date.day self.week = date.isocalendar()[1] self.day_of_week = date.isoweekday() self.score = score self.search_count = search_count
def get_most_recent_day(isoweekday: int, time: dt.time = None, datetime: dt.datetime = None): if not datetime: datetime = dt.datetime.today() if not time: time = dt.time(6, 0) datetime = datetime - dt.timedelta( hours=time.hour) + dt.timedelta.resolution datetime = datetime - dt.timedelta( days=(datetime.isoweekday() - isoweekday) % 7) return dt.datetime.combine(datetime.date(), dt.time(6, 0))
def pack(datetime: dt.datetime) -> bytes: """Pack the timestamp to be sent over the Broadlink protocol.""" data = bytearray(12) utcoffset = int(datetime.utcoffset().total_seconds() / 3600) data[:0x04] = utcoffset.to_bytes(4, "little", signed=True) data[0x04:0x06] = datetime.year.to_bytes(2, "little") data[0x06] = datetime.minute data[0x07] = datetime.hour data[0x08] = int(datetime.strftime("%y")) data[0x09] = datetime.isoweekday() data[0x0A] = datetime.day data[0x0B] = datetime.month return data
def get_trading_date(dt: datetime = None): """ 根据输入的时间,返回交易日的日期 :param dt: :return: """ if dt is None: dt = datetime.now() if dt.isoweekday() in [6, 7]: # 星期六,星期天=>星期一 return (dt + timedelta(days=8 - dt.isoweekday())).strftime('%Y-%m-%d') if dt.hour >= 20: if dt.isoweekday() == 5: # 星期五=》星期一 return (dt + timedelta(days=3)).strftime('%Y-%m-%d') else: # 第二天 return (dt + timedelta(days=1)).strftime('%Y-%m-%d') else: return dt.strftime('%Y-%m-%d')
def guess_next_update_utc(dt: datetime = datetime.now(timezone.utc)) \ -> Tuple[datetime, bool]: """ Make a sensible guess at earliest possible datetime of next update. Guess is based on provided datetime. Parameters ---------- dt : datetime The datetime to use as the basis for comparison to guess the "next update" datetime. Returns ------- Tuple[datetime, bool] A UTC-based datetime for the next update; a boolean that indicates whether the provided dt is likely to coincide with a publish process, which is the APPROX_PUBLISH_DURATION window starting 20:00 on the normal publish days specified by PUBLISH_ISO_WEEKDAYS. """ config = get_application_config() tz = gettz(config.get('ARXIV_BUSINESS_TZ', 'US/Eastern')) dt = dt.astimezone(tz=tz) possible_publish_dt = dt.replace(hour=20, minute=0, second=0) after_todays_publish: bool = dt >= possible_publish_dt likely_in_publish = False delta_to_next_publish = timedelta(days=0) weekday = dt.isoweekday() if after_todays_publish: delta_to_next_publish = timedelta(days=1) if dt < (possible_publish_dt + APPROX_PUBLISH_DURATION) \ and weekday in PUBLISH_ISO_WEEKDAYS: likely_in_publish = True if weekday == 4 and after_todays_publish: # It's Thursday and after publish; next update would be Sunday delta_to_next_publish = timedelta(days=3) elif weekday in (5, 6): # It's Friday or Saturday days_to_add = 7 - weekday delta_to_next_publish = timedelta(days=days_to_add) possible_publish_dt = possible_publish_dt + delta_to_next_publish return (possible_publish_dt.astimezone(tz=tzutc()), likely_in_publish)
def is_in_night_hours(self, time: datetime.datetime) -> bool: ''' Check if the given time is in any night hours. ''' if time.isoweekday() not in settings.NIGHT_HOURS_CONFIG[ constants.DAYS_KEY]: return False minute_range = [] for i in settings.NIGHT_HOURS_CONFIG[constants.TIME_RANGE_KEY]: minute_range.extend(convert_time_range_to_minute_range(i)) current_minute = time.hour * constants.MINUTES_OF_ONE_HOUR + time.minute for r in minute_range: if current_minute in range(r[0], r[1]): return True return False
def _get_dt_param(identifier: str, dt: datetime.datetime) -> int: if identifier == "y": return dt.year elif identifier == "M": return dt.month elif identifier == "d": return dt.isoweekday() elif identifier == "D": return dt.day elif identifier == "h": return dt.hour elif identifier == "m": return dt.minute elif identifier == "s": return dt.second
def work_hours_for_date(self, date: datetime, student: "Student" = None): car = self.cars.first() if student: car = student.car work_hours = self.work_days.filter_by(on_date=date.date(), car=car).all() if not work_hours: weekday = ["NEVER USED", 1, 2, 3, 4, 5, 6, 0][date.isoweekday()] # converty sundays to 0 work_hours = self.work_days.filter_by(day=weekday).all() logger.debug(f"No specific days found. Going with default") logger.debug( f"found these work days on the specific date: {work_hours}") return work_hours
def humanize_absolute_date(value: datetime, now: Optional[datetime] = None): if not now: now = timezone.now() delta = relativedelta(now, value) yesterday = now - relativedelta(days=1) is_older_than_a_week = delta.years > 0 or delta.months > 0 or delta.weeks > 0 if is_older_than_a_week: return formats.date_format(value, 'SHORT_DATE_FORMAT') elif value.day == now.day: return 'Today' elif value.day == yesterday.day: return 'Yesterday' else: return weekday_names[value.isoweekday()]
def get_name_of_weekday(date: datetime): day = date.isoweekday() if day == 1: return "Monday" elif day == 2: return "Tuesday" elif day == 3: return "Wednesday" elif day == 4: return "Thursday" elif day == 5: return "Friday" elif day == 6: return "Saturday" elif day == 7: return "Sunday"
def get_bytes_from_date_day_time(datetime_to_set: datetime): """ Get the 7byte representation of a date object. """ date_list = [] date_list.append(datetime_to_set.second) date_list.append(datetime_to_set.minute) date_list.append(datetime_to_set.hour) date_list.append(datetime_to_set.day) date_list.append(datetime_to_set.month) date_list.append(datetime_to_set.isoweekday()) # 1=Monday 7=Sunday date_list.append(datetime_to_set.year - 2000) # 2000 + byte date_bytes = const.StructDateDayTime.pack(date_list) return date_bytes