Beispiel #1
0
 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)
     )
Beispiel #2
0
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)
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
 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))
Beispiel #7
0
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
Beispiel #8
0
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()))
Beispiel #9
0
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
Beispiel #10
0
 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
Beispiel #11
0
 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
Beispiel #12
0
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
Beispiel #13
0
 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())
Beispiel #14
0
    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()
Beispiel #15
0
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)
Beispiel #16
0
    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())
Beispiel #17
0
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
Beispiel #18
0
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)
Beispiel #20
0
    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)
Beispiel #21
0
 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
Beispiel #22
0
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))
Beispiel #23
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')
Beispiel #25
0
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)
Beispiel #26
0
 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
Beispiel #27
0
 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
Beispiel #28
0
    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
Beispiel #29
0
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()]
Beispiel #30
0
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"
Beispiel #31
0
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