Esempio n. 1
0
def time(match):
    group = match.groupdict()
    data = {k: int(v or 0) for k, v in group.items() if k != 'sign'}
    sign = group.get('sign')
    if sign:
        hours = data['offset_hour']
        minutes = data['offset_minute']
        if hours == minutes == 0:
            raise ValueError('Invalid timezone offset {0}00:00.'.format(sign))

        if sign == '+':
            tz = timezone(hours=hours, minutes=minutes)
        else:
            tz = -timezone(hours=hours, minutes=minutes)
        explicit_tz = True
    else:
        explicit_tz = False
        tz = utc

    hour, minute = data['hour'], data['minute']
    second, millisecond = data['second'], data['millisecond']
    day = 0
    if hour == 24 and minute == second == millisecond == 0:
        hour = 0
        day = 1

    return (time_(hour, minute, second, 1000 * millisecond, tz), day, explicit_tz)
Esempio n. 2
0
def to_time(dt, tzinfo=None, format=None):
    """
    Convert a datetime to time with tzinfo
    """
    d = to_datetime(dt, tzinfo, format)
    if not d:
        return d
    return time_(d.hour, d.minute, d.second, d.microsecond, tzinfo=d.tzinfo)
Esempio n. 3
0
File: date.py Progetto: pyzh/uliweb
def to_time(dt, tzinfo=None, format=None):
    """
    Convert a datetime to time with tzinfo
    """
    d = to_datetime(dt, tzinfo, format)
    if not d:
        return d
    return time_(d.hour, d.minute, d.second, d.microsecond, tzinfo=d.tzinfo)
Esempio n. 4
0
def edit_date(date):
    s = date.split('T')
    yyyymmdd = s[0].split('-')
    ddmmyyyy = yyyymmdd[2] + "." + yyyymmdd[1] + "." + yyyymmdd[0]
    temp = s[1]
    my_date = ddmmyyyy.split('.')
    my_time = temp[:8].split(':')
    new_date = dt(int(my_date[2]), int(my_date[1]), int(my_date[0]))
    new_time = time_(int(my_time[0]), int(my_time[1]), int(my_time[2]))
    return new_date, new_time
Esempio n. 5
0
def datetime_builder_partial(string, delta=None, other=None, strict=False):
    def resolve_tz(value, other, explicit=True):
        """If end does not have a tzinfo attribute, but
        start does, modify end to have a tzinfo attribute.
        """
        if (not explicit or value.tzinfo == None) and (other and other.tzinfo != None):
            return value.replace(tzinfo=other.tzinfo)
        return value

    # select builder
    if strict:
        selected_builder = date_builder_strict
    else:
        selected_builder = date_builder_partial

    # date and time components
    components = string.split('T')
    length = len(components)
    if length == 2:
        try:
            [date, time] = components
            (t, extra_day, explicit_tz) = time_builder(time)
            print('EXPLICIT: %s' % explicit_tz)
            t = resolve_tz(t, other, explicit_tz)
            d = selected_builder(date, other) + timedelta(days=extra_day)
            return datetime_.combine(d, t)
        except:
            raise ValueError('Parsing failed.')
    elif length == 1:
        # only date component
        try:
            if delta:
                d = selected_builder(string, other) + delta
            else:
                d = selected_builder(string, other)
            return resolve_tz(datetime_.combine(d, time_(0, tzinfo=utc)), other)
        # only time component
        except:
            try:
                (t, extra_day, explicit_tz) = time_builder(string)
                t = resolve_tz(t, other, explicit_tz)
                return datetime_.combine(other.date(), t)
            except:
                raise ValueError('Parsing failed.')
    else:
        raise ValueError('Parsing failed.')
Esempio n. 6
0
def update_schedule(name, days, hours):
    """
        Create or update and return a schedule, assuming days as a list of
        numbers enumerating the days of the week (0-6) and hours a list of
        tuples of hours and minutes [(h m), ...].
    """

    # Get
    schedule = DB.query(Schedule).filter(Schedule.name == name).first()

    # Or create
    if schedule is None:
        schedule = Schedule()
        schedule.name = name
        DB.add(schedule)
        DB.flush()

    # Days of the week
    schedule.monday = True if 0 in days else False
    schedule.tuesday = True if 1 in days else False
    schedule.wednesday = True if 2 in days else False
    schedule.thursday = True if 3 in days else False
    schedule.friday = True if 4 in days else False
    schedule.saturday = True if 5 in days else False
    schedule.sunday = True if 6 in days else False

    # New hours
    DB.query(Time).filter(Time.schedule_id == schedule.id).delete()
    for h_m in hours:
        hour = Time()
        hour.time = time_(int(h_m[0]), int(h_m[1]))
        hour.schedule_id = schedule.id
        DB.add(hour)

    # Save
    DB.commit()

    return schedule
Esempio n. 7
0
def calendar_add(caldav_conn, args):
    cal = Calendar()
    cal.add(
        'prodid', '-//{author_short}//{product}//{language}'.format(
            author_short=__author_short__,
            product=__product__,
            language=args.language))
    cal.add('version', '2.0')
    event = Event()
    ## read timestamps from arguments
    event_spec = args.event_time.split('+')
    if len(event_spec) > 3:
        raise ValueError(
            'Invalid event time "%s" - can max contain 2 plus-signs' %
            args.event_time)
    elif len(event_spec) == 3:
        event_time = '%s+%s' % tuple(event_spec[0:2])
        event_duration = event_spec[2]
    elif len(event_spec) == 2 and not event_spec[1][-1:] in time_units:
        event_time = '%s+%s' % tuple(event_spec[0:2])
        event_duration = '1h'
    elif len(event_spec) == 2:
        event_time = '%s' % event_spec[0]
        event_duration = event_spec[1]
    else:
        event_time = event_spec[0]
        event_duration = '1h'
    ## TODO: error handling
    event_duration_secs = float(
        event_duration[:-1]) * time_units[event_duration[-1:]]
    dtstart = dateutil.parser.parse(event_spec[0], ignoretz=True)
    if (args.whole_day
            or (event_duration_secs %
                (60 * 60 * 24) == 0 and dtstart.time() == time_(0, 0))):

        ## allowing 1 second off due to leap seconds
        if (event_duration_secs + 1) % (60 * 60 * 24) > 2:
            raise ValueError(
                'Duration of whole-day event must be multiple of 1d')

        duration = event_duration_secs // 60 // 60 // 24
        dtend = dtstart + timedelta(days=duration)
        event.add('dtstart', _date(dtstart.date()))
        event.add('dtend', _date(dtend.date()))
    else:
        dtstart = _tz(args.timezone).localize(dtstart)
        event.add('dtstart', dtstart)
        ## TODO: handle duration and end-time as options.  default 3600s by now.
        event.add('dtend', dtstart + timedelta(0, event_duration_secs))
    if (args.private):
        event.add('class', 'PRIVATE')
    event.add('dtstamp', _now())
    uid = uuid.uuid1()
    event.add('uid', str(uid))
    for attr in vcal_txt_one + vcal_txt_many:
        if attr == 'summary':
            continue
        val = getattr(args, 'set_' + attr)
        if val:
            event.add(attr, val)
    event.add('summary', ' '.join(args.summary))
    event.add(
        'description',
        ' '.join(args.description.replace('\\n', '\n').replace('\\t', '\t')))
    cal.add_component(event)
    ## workaround for getting RFC-compliant ical data,
    ## ref https://github.com/collective/icalendar/issues/272#issuecomment-640204031
    ical_data = vobject.readOne(cal.to_ical().decode('utf-8')).serialize()
    _calendar_addics(caldav_conn, ical_data, uid, args)
    print("Added event with uid=%s" % uid)
Esempio n. 8
0
    time_: lambda value: 'm_%s' % _time_encode(value),
    timedelta: lambda value: 'e_%i.%i.%i' % (value.days, value.seconds, value.microseconds),
    tuple: lambda value: 'l_' + '_'.join(map(lambda a: _escape(encode(a)), value)),
    list: lambda value: 'l_' + '_'.join(map(lambda a: _escape(encode(a)), value)),
    dict: lambda value: 'h_' + '_'.join(map(lambda a: '%s:%s' % (_escape(encode(a[0])), _escape(encode(a[1]))), value.items())),
}

decodings = {
    'N': lambda value: None,
    'i': int,
    'f': float,
    'b': lambda value: bool(int(value)),
    'd': Decimal,
    'u': lambda value: _unescape(value).decode('base-64').decode('utf-8'),
    # NOTE: Read this stackoverflow for more info on why this needs to be done this way.
    # This is just needs to use utcfromtimestamp since we are using utcfromtimestamp above
    # https://stackoverflow.com/questions/8777753/converting-datetime-date-to-utc-timestamp-in-python
    't': lambda value: datetime.utcfromtimestamp(float(value)),
    'a': lambda value: date.fromtimestamp(float(value)),
    'm': lambda value: time_(*map(int, value.split('.'))),
    'e': lambda value: timedelta(*map(int, value.split('.'))),
    'l': lambda value: map(decode, map(_unescape, value.split('_'))),
    'h': lambda value: dict(map(lambda a: map(decode, map(_unescape, a.split(':'))), value.split('_'))),
}

def _escape(value):
    return value.replace('|', '||').replace('\n', '|n').replace('_', '|u')

def _unescape(value):
    return value.replace('||', '|').replace('|n', '\n').replace('|u', '_')
Esempio n. 9
0
def test_time():
    with pytest.raises(ValueError):
        parsers.time('1234a')
       
    with pytest.raises(ValueError):
        parsers.time('1234a')

    with pytest.raises(ValueError):
        parsers.time('12:30:40.05+0:15')

    with pytest.raises(ValueError):
        parsers.time('1230401.05+10:15')

    with pytest.raises(ValueError):
        parsers.time('24:00:00.0001')

    assert parsers.time('24:00:00') == parsers.time('00:00:00')
    assert parsers.time('12') == time_(hour=12, tzinfo=utc)
    assert parsers.time('12+05:10') == time_(hour=12, tzinfo=timezone(hours=5, minutes=10))
    assert parsers.time('12-05:10') == time_(hour=12, tzinfo=-timezone(hours=5, minutes=10))
    assert parsers.time('13:15') == time_(hour=13, minute=15, tzinfo=utc)
    assert parsers.time('13:15+05:10') == time_(hour=13, minute=15, tzinfo=timezone(hours=5, minutes=10))
    assert parsers.time('13:15-05:10') == time_(hour=13, minute=15, tzinfo=-timezone(hours=5, minutes=10))
    assert parsers.time('14:20:50') == time_(hour=14, minute=20, second=50, tzinfo=utc)
    assert parsers.time('14:20:50+05:10') == time_(hour=14, minute=20, second=50, tzinfo=timezone(hours=5, minutes=10))
    assert parsers.time('14:20:50-05:10') == time_(hour=14, minute=20, second=50, tzinfo=-timezone(hours=5, minutes=10))
    assert parsers.time('14:20:50+05') == time_(hour=14, minute=20, second=50, tzinfo=timezone(hours=5))
    assert parsers.time('14:20:50-05') == time_(hour=14, minute=20, second=50, tzinfo=-timezone(hours=5))
    assert parsers.time('14:20:50+0510') == time_(hour=14, minute=20, second=50, tzinfo=timezone(hours=5, minutes=10))
    assert parsers.time('14:20:50-0510') == time_(hour=14, minute=20, second=50, tzinfo=-timezone(hours=5, minutes=10))
    assert parsers.time('12:30:40.05') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=utc)
    assert parsers.time('12:30:40.05Z') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=utc)
    assert parsers.time('12:30:40.05+10:15') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=timezone(hours=10, minutes=15))
    assert parsers.time('12:30:40.05-08:45') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=-timezone(hours=8, minutes=45))
    assert parsers.time('1315') == time_(hour=13, minute=15, tzinfo=utc)
    assert parsers.time('1315+05:10') == time_(hour=13, minute=15, tzinfo=timezone(hours=5, minutes=10))
    assert parsers.time('1315-05:10') == time_(hour=13, minute=15, tzinfo=-timezone(hours=5, minutes=10))
    assert parsers.time('142050'), time_(hour=14, minute=20, second=50, tzinfo=utc)
    assert parsers.time('142050+05:10') == time_(hour=14, minute=20, second=50, tzinfo=timezone(hours=5, minutes=10))
    assert parsers.time('142050-05:10') == time_(hour=14, minute=20, second=50, tzinfo=-timezone(hours=5, minutes=10))
    assert parsers.time('142050+05') == time_(hour=14, minute=20, second=50, tzinfo=timezone(hours=5))
    assert parsers.time('142050-05') == time_(hour=14, minute=20, second=50, tzinfo=-timezone(hours=5))
    assert parsers.time('142050+0510') == time_(hour=14, minute=20, second=50, tzinfo=timezone(hours=5, minutes=10))
    assert parsers.time('142050-0510') == time_(hour=14, minute=20, second=50, tzinfo=-timezone(hours=5, minutes=10))
    assert parsers.time('123040.05') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=utc)
    assert parsers.time('123040.05Z') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=utc)
    assert parsers.time('123040.05+10:15') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=timezone(hours=10, minutes=15))
    assert parsers.time('123040.05-08:45') == time_(hour=12, minute=30, second=40, microsecond=5000, tzinfo=-timezone(hours=8, minutes=45))
Esempio n. 10
0
def process_queue():
    """
        First update all schedules and data from the watch list files, then
        tweet queued post based on the schedules. One at a time.
    """

    # Update data from the watch list

    print(f"Updating data from files in the watch list...")

    watch = DB.query(Watch).all()
    for w in watch:
        update_from_file(w.path)

    # What day are we?
    today = datetime.today()

    strday = str(get_schedule_column(today.weekday())).replace("Schedule.", "")
    print(
        f"\nQueue processing started "
        f"({strday.title()} {today.date()} {today.time().replace(microsecond=0)})"
    )

    # Get all the schedules for today
    todaysched = DB.query(Schedule).filter(get_schedule_column(
        today.weekday())).all()

    if not todaysched:
        print("No schedules today")

    # Look for an hour that fits, less than current hour, bigger that the
    # application start time hour if we are on the same day
    for tsc in todaysched:

        if START.date() == today.date():
            startime = START.time().replace(second=0, microsecond=0)
        else:
            startime = time_()

        hour = DB.query(Time).filter(
            and_(Time.schedule_id == tsc.id, Time.used < today.date(),
                 Time.time <= today.time(), Time.time >= startime)).first()

        print(f"\nSchedule '{tsc.name}'")

        if hour:

            print(f"At {hour.time}")

            # Get the first unpublished post of the schedule in the hour that
            # isn't an error
            post = DB.query(Post).filter(
                and_(Post.schedule_id == hour.schedule_id, Post.published == 0,
                     Post.error == 0)).first()

            if post:

                # Announce

                print(
                    f"Trying to tweet:\n{post.text} {post.image_url if post.image_url else ''}"
                )

                # Twitter auth and tokens validation

                tokens = json.load(open(TOKENS_FILE, 'r'))

                auth = tweepy.OAuthHandler(tokens[tsc.name]['consumer_key'],
                                           tokens[tsc.name]['consumer_secret'])
                auth.set_access_token(tokens[tsc.name]['oauth_token'],
                                      tokens[tsc.name]['oauth_secret'])

                if not tokens[tsc.name]['consumer_key']:
                    print(
                        f"The schedule '{tsc.name}' doesn't have the Twitter tokens, add them to the tokens file!"
                    )
                    continue

                # Tweet

                else:

                    api = tweepy.API(auth,
                                     wait_on_rate_limit=True,
                                     wait_on_rate_limit_notify=True)

                    try:
                        if post.image_url:
                            api.update_with_media(post.image_url, post.text)
                        else:
                            api.update_status(post.text)
                        print(f"Done!")

                        # Mark the post as published, and register the hour used time

                        post.published = True
                        DB.add(post)

                        hour.used = datetime.now()
                        DB.add(hour)

                        DB.commit()

                    except tweepy.error.TweepError as err:
                        print(f"Skipped, error: {err}")

                        post.error = True
                        DB.add(post)
                        DB.commit()

            else:
                print("The queue is empty!")

        else:
            print(f"No pending hours!")